@@ -68,6 +68,64 @@ static char *fix_filename(const char *prefix, const char *file)
68
68
return prefix_filename_except_for_dash (prefix , file );
69
69
}
70
70
71
+ static int do_get_int_value (const void * value , size_t precision , intmax_t * ret )
72
+ {
73
+ switch (precision ) {
74
+ case sizeof (int8_t ):
75
+ * ret = * (int8_t * )value ;
76
+ return 0 ;
77
+ case sizeof (int16_t ):
78
+ * ret = * (int16_t * )value ;
79
+ return 0 ;
80
+ case sizeof (int32_t ):
81
+ * ret = * (int32_t * )value ;
82
+ return 0 ;
83
+ case sizeof (int64_t ):
84
+ * ret = * (int64_t * )value ;
85
+ return 0 ;
86
+ default :
87
+ return -1 ;
88
+ }
89
+ }
90
+
91
+ static intmax_t get_int_value (const struct option * opt , enum opt_parsed flags )
92
+ {
93
+ intmax_t ret ;
94
+ if (do_get_int_value (opt -> value , opt -> precision , & ret ))
95
+ BUG ("invalid precision for option %s" , optname (opt , flags ));
96
+ return ret ;
97
+ }
98
+
99
+ static enum parse_opt_result set_int_value (const struct option * opt ,
100
+ enum opt_parsed flags ,
101
+ intmax_t value )
102
+ {
103
+ switch (opt -> precision ) {
104
+ case sizeof (int8_t ):
105
+ * (int8_t * )opt -> value = value ;
106
+ return 0 ;
107
+ case sizeof (int16_t ):
108
+ * (int16_t * )opt -> value = value ;
109
+ return 0 ;
110
+ case sizeof (int32_t ):
111
+ * (int32_t * )opt -> value = value ;
112
+ return 0 ;
113
+ case sizeof (int64_t ):
114
+ * (int64_t * )opt -> value = value ;
115
+ return 0 ;
116
+ default :
117
+ BUG ("invalid precision for option %s" , optname (opt , flags ));
118
+ }
119
+ }
120
+
121
+ static int signed_int_fits (intmax_t value , size_t precision )
122
+ {
123
+ size_t bits = precision * CHAR_BIT ;
124
+ intmax_t upper_bound = INTMAX_MAX >> (bitsizeof (intmax_t ) - bits );
125
+ intmax_t lower_bound = - upper_bound - 1 ;
126
+ return lower_bound <= value && value <= upper_bound ;
127
+ }
128
+
71
129
static enum parse_opt_result do_get_value (struct parse_opt_ctx_t * p ,
72
130
const struct option * opt ,
73
131
enum opt_parsed flags ,
@@ -89,35 +147,55 @@ static enum parse_opt_result do_get_value(struct parse_opt_ctx_t *p,
89
147
return opt -> ll_callback (p , opt , NULL , unset );
90
148
91
149
case OPTION_BIT :
150
+ {
151
+ intmax_t value = get_int_value (opt , flags );
92
152
if (unset )
93
- * ( int * ) opt -> value &= ~opt -> defval ;
153
+ value &= ~opt -> defval ;
94
154
else
95
- * (int * )opt -> value |= opt -> defval ;
96
- return 0 ;
155
+ value |= opt -> defval ;
156
+ return set_int_value (opt , flags , value );
157
+ }
97
158
98
159
case OPTION_NEGBIT :
160
+ {
161
+ intmax_t value = get_int_value (opt , flags );
99
162
if (unset )
100
- * ( int * ) opt -> value |= opt -> defval ;
163
+ value |= opt -> defval ;
101
164
else
102
- * (int * )opt -> value &= ~opt -> defval ;
103
- return 0 ;
165
+ value &= ~opt -> defval ;
166
+ return set_int_value (opt , flags , value );
167
+ }
104
168
105
169
case OPTION_BITOP :
170
+ {
171
+ intmax_t value = get_int_value (opt , flags );
106
172
if (unset )
107
173
BUG ("BITOP can't have unset form" );
108
- * (int * )opt -> value &= ~opt -> extra ;
109
- * (int * )opt -> value |= opt -> defval ;
110
- return 0 ;
174
+ value &= ~opt -> extra ;
175
+ value |= opt -> defval ;
176
+ return set_int_value (opt , flags , value );
177
+ }
111
178
112
179
case OPTION_COUNTUP :
113
- if (* (int * )opt -> value < 0 )
114
- * (int * )opt -> value = 0 ;
115
- * (int * )opt -> value = unset ? 0 : * (int * )opt -> value + 1 ;
116
- return 0 ;
180
+ {
181
+ size_t bits = CHAR_BIT * opt -> precision ;
182
+ intmax_t upper_bound = INTMAX_MAX >> (bitsizeof (intmax_t ) - bits );
183
+ intmax_t value = get_int_value (opt , flags );
184
+
185
+ if (value < 0 )
186
+ value = 0 ;
187
+ if (unset )
188
+ value = 0 ;
189
+ else if (value < upper_bound )
190
+ value ++ ;
191
+ else
192
+ return error (_ ("value for %s exceeds %" PRIdMAX ),
193
+ optname (opt , flags ), upper_bound );
194
+ return set_int_value (opt , flags , value );
195
+ }
117
196
118
197
case OPTION_SET_INT :
119
- * (int * )opt -> value = unset ? 0 : opt -> defval ;
120
- return 0 ;
198
+ return set_int_value (opt , flags , unset ? 0 : opt -> defval );
121
199
122
200
case OPTION_STRING :
123
201
if (unset )
@@ -199,23 +277,7 @@ static enum parse_opt_result do_get_value(struct parse_opt_ctx_t *p,
199
277
return error (_ ("value %s for %s not in range [%" PRIdMAX ",%" PRIdMAX "]" ),
200
278
arg , optname (opt , flags ), (intmax_t )lower_bound , (intmax_t )upper_bound );
201
279
202
- switch (opt -> precision ) {
203
- case 1 :
204
- * (int8_t * )opt -> value = value ;
205
- return 0 ;
206
- case 2 :
207
- * (int16_t * )opt -> value = value ;
208
- return 0 ;
209
- case 4 :
210
- * (int32_t * )opt -> value = value ;
211
- return 0 ;
212
- case 8 :
213
- * (int64_t * )opt -> value = value ;
214
- return 0 ;
215
- default :
216
- BUG ("invalid precision for option %s" ,
217
- optname (opt , flags ));
218
- }
280
+ return set_int_value (opt , flags , value );
219
281
}
220
282
case OPTION_UNSIGNED :
221
283
{
@@ -266,7 +328,9 @@ static enum parse_opt_result do_get_value(struct parse_opt_ctx_t *p,
266
328
}
267
329
268
330
struct parse_opt_cmdmode_list {
269
- int value , * value_ptr ;
331
+ intmax_t value ;
332
+ void * value_ptr ;
333
+ size_t precision ;
270
334
const struct option * opt ;
271
335
const char * arg ;
272
336
enum opt_parsed flags ;
@@ -280,7 +344,7 @@ static void build_cmdmode_list(struct parse_opt_ctx_t *ctx,
280
344
281
345
for (; opts -> type != OPTION_END ; opts ++ ) {
282
346
struct parse_opt_cmdmode_list * elem = ctx -> cmdmode_list ;
283
- int * value_ptr = opts -> value ;
347
+ void * value_ptr = opts -> value ;
284
348
285
349
if (!(opts -> flags & PARSE_OPT_CMDMODE ) || !value_ptr )
286
350
continue ;
@@ -292,10 +356,13 @@ static void build_cmdmode_list(struct parse_opt_ctx_t *ctx,
292
356
293
357
CALLOC_ARRAY (elem , 1 );
294
358
elem -> value_ptr = value_ptr ;
295
- elem -> value = * value_ptr ;
359
+ elem -> precision = opts -> precision ;
360
+ if (do_get_int_value (value_ptr , opts -> precision , & elem -> value ))
361
+ optbug (opts , "has invalid precision" );
296
362
elem -> next = ctx -> cmdmode_list ;
297
363
ctx -> cmdmode_list = elem ;
298
364
}
365
+ BUG_if_bug ("invalid 'struct option'" );
299
366
}
300
367
301
368
static char * optnamearg (const struct option * opt , const char * arg ,
@@ -317,7 +384,13 @@ static enum parse_opt_result get_value(struct parse_opt_ctx_t *p,
317
384
char * opt_name , * other_opt_name ;
318
385
319
386
for (; elem ; elem = elem -> next ) {
320
- if (* elem -> value_ptr == elem -> value )
387
+ intmax_t new_value ;
388
+
389
+ if (do_get_int_value (elem -> value_ptr , elem -> precision ,
390
+ & new_value ))
391
+ BUG ("impossible: invalid precision" );
392
+
393
+ if (new_value == elem -> value )
321
394
continue ;
322
395
323
396
if (elem -> opt &&
@@ -327,7 +400,7 @@ static enum parse_opt_result get_value(struct parse_opt_ctx_t *p,
327
400
elem -> opt = opt ;
328
401
elem -> arg = arg ;
329
402
elem -> flags = flags ;
330
- elem -> value = * elem -> value_ptr ;
403
+ elem -> value = new_value ;
331
404
}
332
405
333
406
if (result || !elem )
@@ -586,10 +659,14 @@ static void parse_options_check(const struct option *opts)
586
659
opts -> long_name && !(opts -> flags & PARSE_OPT_NONEG ))
587
660
optbug (opts , "OPTION_SET_INT 0 should not be negatable" );
588
661
switch (opts -> type ) {
589
- case OPTION_COUNTUP :
662
+ case OPTION_SET_INT :
590
663
case OPTION_BIT :
591
664
case OPTION_NEGBIT :
592
- case OPTION_SET_INT :
665
+ case OPTION_BITOP :
666
+ case OPTION_COUNTUP :
667
+ if (!signed_int_fits (opts -> defval , opts -> precision ))
668
+ optbug (opts , "has invalid defval" );
669
+ /* fallthru */
593
670
case OPTION_NUMBER :
594
671
if ((opts -> flags & PARSE_OPT_OPTARG ) ||
595
672
!(opts -> flags & PARSE_OPT_NOARG ))
0 commit comments