33#include "../../../include/libc/unistd.h"
44#include "../../../include/libc/stdint.h"
55
6+ // BAD
67// from https://github.com/apple-oss-distributions/Libinfo/blob/9fce29e5c5edc15d3ecea55116ca17d3f6350603/lookup.subproj/mdns_module.c#L1033C1-L1079C2
78char * _mdns_parse_domain_name (const uint8_t * data , uint32_t datalen )
89{
@@ -20,18 +21,18 @@ char* _mdns_parse_domain_name(const uint8_t *data, uint32_t datalen)
2021
2122 if (domain == NULL ) return NULL ;
2223
23- if (len == 0 ) break ; // DNS root (NUL)
24+ if (len == 0 ) break ;
2425
2526 if (j > 0 )
2627 {
2728 domain [j ++ ] = datalen ? '.' : '\0' ;
2829 }
2930
31+ // bug is in datalen decrementation here
3032 while ((len -- > 0 ) && (0 != datalen -- ))
3133 {
3234 if (data [i ] == '.' )
3335 {
34- /* special case: escape the '.' with a '\' */
3536 domain = reallocf (domain , ++ domainlen );
3637 if (domain == NULL ) return NULL ;
3738
@@ -47,6 +48,106 @@ char* _mdns_parse_domain_name(const uint8_t *data, uint32_t datalen)
4748 return domain ;
4849}
4950
51+ // BAD: n used after loop without overwrite (overflowed on last iteration)
52+ void simple_use_after_loop (uint32_t n , int * buf ) {
53+ while (n -- > 0 ) {
54+ buf [0 ] = 1 ;
55+ }
56+ buf [n ] = 0 ; // BAD: n is UINT32_MAX here
57+ }
58+
59+ // BAD: use in false branch of != 0
60+ void use_after_neq (uint32_t n , int * buf ) {
61+ if (n -- != 0 ) {
62+ buf [0 ] = 1 ;
63+ }
64+ buf [n ] = 0 ; // BAD
65+ }
66+
67+ // GOOD: variable overwritten by assignment before use
68+ void overwrite_by_assignment (uint32_t n , int * buf ) {
69+ while (n -- > 0 ) {
70+ buf [0 ] = 1 ;
71+ }
72+ n = 42 ;
73+ buf [n ] = 0 ;
74+ }
75+
76+ // GOOD: signed integer - not unsigned
77+ void signed_decrement (int n , int * buf ) {
78+ while (n -- > 0 ) {
79+ buf [n ] = 0 ;
80+ }
81+ }
82+
83+ // GOOD: variable not used after comparison
84+ void no_use_after (uint32_t n , int * buf ) {
85+ while (n -- > 0 ) {
86+ buf [0 ] = 1 ;
87+ }
88+ }
89+
90+ // BAD: reversed comparison form 0 < n--
91+ void reversed_lt (uint32_t n , int * buf ) {
92+ while (0 < n -- ) {
93+ buf [0 ] = 1 ;
94+ }
95+ buf [n ] = 0 ; // BAD
96+ }
97+
98+ // BAD: n-- == 0, use in true branch where n just wrapped to UINT32_MAX
99+ void eq_zero (uint32_t n , int * buf ) {
100+ if (n -- == 0 ) {
101+ buf [n ] = 0 ; // BAD
102+ }
103+ }
104+
105+ // BAD: do-while, use after loop
106+ void do_while (uint32_t n , int * buf ) {
107+ do {
108+ buf [0 ] = 1 ;
109+ } while (n -- > 0 );
110+ buf [n ] = 0 ; // BAD
111+ }
112+
113+ // BAD: conditional overwrite (only one branch overwrites)
114+ void conditional_overwrite (uint32_t n , int * buf , int cond ) {
115+ if (n -- != 0 ) {
116+ buf [0 ] = 1 ;
117+ }
118+ if (cond ) {
119+ n = 42 ;
120+ }
121+ buf [n ] = 0 ; // BAD: path exists where n is not overwritten
122+ }
123+
124+ // GOOD: use only in true branch of > 0 (n was confirmed > 0)
125+ void use_in_true_branch (uint32_t n , int * buf ) {
126+ if (n -- > 0 ) {
127+ buf [n ] = 0 ;
128+ }
129+ }
130+
131+ // GOOD: prefix decrement (query only checks postfix)
132+ void prefix_decrement (uint32_t n , int * buf ) {
133+ while (-- n > 0 ) {
134+ buf [n ] = 0 ;
135+ }
136+ }
137+
138+ // GOOD: overwrite in all branches before use
139+ void overwrite_all_branches (uint32_t n , int * buf , int cond ) {
140+ while (n -- > 0 ) {
141+ buf [0 ] = 1 ;
142+ }
143+ if (cond ) {
144+ n = 10 ;
145+ } else {
146+ n = 20 ;
147+ }
148+ buf [n ] = 0 ;
149+ }
150+
50151int main () {
51152 const uint16_t datalen = 128 ;
52153 uint8_t data [datalen ] = {};
0 commit comments