@@ -419,10 +419,7 @@ static_assert(SMALL == ('a' ^ 'A'));
419
419
420
420
enum format_state {
421
421
FORMAT_STATE_NONE , /* Just a string part */
422
- FORMAT_STATE_1BYTE = 1 , /* char/short/int are their own sizes */
423
- FORMAT_STATE_2BYTE = 2 ,
424
- FORMAT_STATE_8BYTE = 3 ,
425
- FORMAT_STATE_4BYTE = 4 ,
422
+ FORMAT_STATE_NUM ,
426
423
FORMAT_STATE_WIDTH ,
427
424
FORMAT_STATE_PRECISION ,
428
425
FORMAT_STATE_CHAR ,
@@ -432,8 +429,6 @@ enum format_state {
432
429
FORMAT_STATE_INVALID ,
433
430
};
434
431
435
- #define FORMAT_STATE_SIZE (type ) (sizeof(type) <= 4 ? sizeof(type) : FORMAT_STATE_8BYTE)
436
-
437
432
struct printf_spec {
438
433
unsigned char flags ; /* flags to number() */
439
434
unsigned char base ; /* number base, 8, 10 or 16 only */
@@ -2523,7 +2518,8 @@ char *pointer(const char *fmt, char *buf, char *end, void *ptr,
2523
2518
2524
2519
struct fmt {
2525
2520
const char * str ;
2526
- enum format_state state ;
2521
+ unsigned char state ; // enum format_state
2522
+ unsigned char size ; // size of numbers
2527
2523
};
2528
2524
2529
2525
#define SPEC_CHAR (x , flag ) [(x)-32] = flag
@@ -2638,20 +2634,21 @@ struct fmt format_decode(struct fmt fmt, struct printf_spec *spec)
2638
2634
qualifier :
2639
2635
/* Set up default numeric format */
2640
2636
spec -> base = 10 ;
2641
- fmt .state = FORMAT_STATE_SIZE (int );
2637
+ fmt .state = FORMAT_STATE_NUM ;
2638
+ fmt .size = sizeof (int );
2642
2639
static const struct format_state {
2643
2640
unsigned char state ;
2644
- unsigned char flags_or_double_state ;
2645
- unsigned char modifier ;
2641
+ unsigned char size ;
2642
+ unsigned char flags_or_double_size ;
2646
2643
unsigned char base ;
2647
2644
} lookup_state [256 ] = {
2648
- // Qualifiers
2649
- ['l' ] = { FORMAT_STATE_SIZE (long ), FORMAT_STATE_SIZE (long long ), 1 },
2650
- ['L' ] = { FORMAT_STATE_SIZE (long long ), 0 , 1 },
2651
- ['h' ] = { FORMAT_STATE_SIZE (short ), FORMAT_STATE_SIZE (char ), 1 },
2652
- ['H' ] = { FORMAT_STATE_SIZE (char ), 0 , 1 }, // Questionable, historic
2653
- ['z' ] = { FORMAT_STATE_SIZE ( size_t ), 0 , 1 },
2654
- ['t' ] = { FORMAT_STATE_SIZE ( ptrdiff_t ), 0 , 1 },
2645
+ // Length
2646
+ ['l' ] = { 0 , sizeof (long ), sizeof (long long ) },
2647
+ ['L' ] = { 0 , sizeof (long long ) },
2648
+ ['h' ] = { 0 , sizeof (short ), sizeof (char ) },
2649
+ ['H' ] = { 0 , sizeof (char ) }, // Questionable historical
2650
+ ['z' ] = { 0 , sizeof ( size_t ) },
2651
+ ['t' ] = { 0 , sizeof ( ptrdiff_t ) },
2655
2652
2656
2653
// Non-numeric formats
2657
2654
['c' ] = { FORMAT_STATE_CHAR },
@@ -2660,12 +2657,12 @@ struct fmt format_decode(struct fmt fmt, struct printf_spec *spec)
2660
2657
['%' ] = { FORMAT_STATE_PERCENT_CHAR },
2661
2658
2662
2659
// Numerics
2663
- ['o' ] = { 0 , 0 , 0 , 8 },
2664
- ['x' ] = { 0 , SMALL , 0 , 16 },
2665
- ['X' ] = { 0 , 0 , 0 , 16 },
2666
- ['d' ] = { 0 , SIGN , 0 , 10 },
2667
- ['i' ] = { 0 , SIGN , 0 , 10 },
2668
- ['u' ] = { 0 , 0 , 0 , 10 , },
2660
+ ['o' ] = { FORMAT_STATE_NUM , 0 , 0 , 8 },
2661
+ ['x' ] = { FORMAT_STATE_NUM , 0 , SMALL , 16 },
2662
+ ['X' ] = { FORMAT_STATE_NUM , 0 , 0 , 16 },
2663
+ ['d' ] = { FORMAT_STATE_NUM , 0 , SIGN , 10 },
2664
+ ['i' ] = { FORMAT_STATE_NUM , 0 , SIGN , 10 },
2665
+ ['u' ] = { FORMAT_STATE_NUM , 0 , 0 , 10 , },
2669
2666
2670
2667
/*
2671
2668
* Since %n poses a greater security risk than
@@ -2675,30 +2672,23 @@ struct fmt format_decode(struct fmt fmt, struct printf_spec *spec)
2675
2672
};
2676
2673
2677
2674
const struct format_state * p = lookup_state + (u8 )* fmt .str ;
2678
- if (p -> modifier ) {
2679
- fmt .state = p -> state ;
2680
- if (p -> flags_or_double_state && fmt .str [0 ] == fmt .str [1 ]) {
2681
- fmt .state = p -> flags_or_double_state ;
2675
+ if (p -> size ) {
2676
+ fmt .size = p -> size ;
2677
+ if (p -> flags_or_double_size && fmt .str [0 ] == fmt .str [1 ]) {
2678
+ fmt .size = p -> flags_or_double_size ;
2682
2679
fmt .str ++ ;
2683
2680
}
2684
2681
fmt .str ++ ;
2685
2682
p = lookup_state + * fmt .str ;
2686
- if (unlikely (p -> modifier ))
2687
- goto invalid ;
2688
- }
2689
- if (p -> base ) {
2690
- spec -> base = p -> base ;
2691
- spec -> flags |= p -> flags_or_double_state ;
2692
- fmt .str ++ ;
2693
- return fmt ;
2694
2683
}
2695
2684
if (p -> state ) {
2685
+ spec -> base = p -> base ;
2686
+ spec -> flags |= p -> flags_or_double_size ;
2696
2687
fmt .state = p -> state ;
2697
2688
fmt .str ++ ;
2698
2689
return fmt ;
2699
2690
}
2700
2691
2701
- invalid :
2702
2692
WARN_ONCE (1 , "Please remove unsupported %%%c in format string\n" , * fmt .str );
2703
2693
fmt .state = FORMAT_STATE_INVALID ;
2704
2694
return fmt ;
@@ -2768,7 +2758,6 @@ static unsigned long long convert_num_spec(unsigned int val, int size, struct pr
2768
2758
*/
2769
2759
int vsnprintf (char * buf , size_t size , const char * fmt_str , va_list args )
2770
2760
{
2771
- unsigned long long num ;
2772
2761
char * str , * end ;
2773
2762
struct printf_spec spec = {0 };
2774
2763
struct fmt fmt = {
@@ -2808,6 +2797,16 @@ int vsnprintf(char *buf, size_t size, const char *fmt_str, va_list args)
2808
2797
continue ;
2809
2798
}
2810
2799
2800
+ case FORMAT_STATE_NUM : {
2801
+ unsigned long long num ;
2802
+ if (fmt .size <= sizeof (int ))
2803
+ num = convert_num_spec (va_arg (args , int ), fmt .size , spec );
2804
+ else
2805
+ num = va_arg (args , long long );
2806
+ str = number (str , end , num , spec );
2807
+ continue ;
2808
+ }
2809
+
2811
2810
case FORMAT_STATE_WIDTH :
2812
2811
set_field_width (& spec , va_arg (args , int ));
2813
2812
continue ;
@@ -2856,7 +2855,7 @@ int vsnprintf(char *buf, size_t size, const char *fmt_str, va_list args)
2856
2855
++ str ;
2857
2856
continue ;
2858
2857
2859
- case FORMAT_STATE_INVALID :
2858
+ default :
2860
2859
/*
2861
2860
* Presumably the arguments passed gcc's type
2862
2861
* checking, but there is no safe or sane way
@@ -2866,17 +2865,7 @@ int vsnprintf(char *buf, size_t size, const char *fmt_str, va_list args)
2866
2865
* sync.
2867
2866
*/
2868
2867
goto out ;
2869
-
2870
- case FORMAT_STATE_8BYTE :
2871
- num = va_arg (args , long long );
2872
- break ;
2873
-
2874
- default :
2875
- num = convert_num_spec (va_arg (args , int ), fmt .state , spec );
2876
- break ;
2877
2868
}
2878
-
2879
- str = number (str , end , num , spec );
2880
2869
}
2881
2870
2882
2871
out :
@@ -3147,17 +3136,20 @@ int vbin_printf(u32 *bin_buf, size_t size, const char *fmt_str, va_list args)
3147
3136
fmt .str ++ ;
3148
3137
break ;
3149
3138
3150
- case FORMAT_STATE_8BYTE :
3151
- save_arg (long long ) ;
3152
- break ;
3153
- case FORMAT_STATE_1BYTE :
3154
- save_arg (char );
3155
- break ;
3156
- case FORMAT_STATE_2BYTE :
3157
- save_arg (short );
3158
- break ;
3159
- default :
3160
- save_arg (int );
3139
+ case FORMAT_STATE_NUM :
3140
+ switch (fmt .size ) {
3141
+ case 8 :
3142
+ save_arg (long long ) ;
3143
+ break ;
3144
+ case 1 :
3145
+ save_arg (char );
3146
+ break ;
3147
+ case 2 :
3148
+ save_arg (short );
3149
+ break ;
3150
+ default :
3151
+ save_arg (int );
3152
+ }
3161
3153
}
3162
3154
}
3163
3155
@@ -3325,18 +3317,21 @@ int bstr_printf(char *buf, size_t size, const char *fmt_str, const u32 *bin_buf)
3325
3317
case FORMAT_STATE_INVALID :
3326
3318
goto out ;
3327
3319
3328
- case FORMAT_STATE_8BYTE :
3329
- num = get_arg (long long );
3330
- break ;
3331
- case FORMAT_STATE_2BYTE :
3332
- num = convert_num_spec (get_arg (short ), fmt .state , spec );
3333
- break ;
3334
- case FORMAT_STATE_1BYTE :
3335
- num = convert_num_spec (get_arg (char ), fmt .state , spec );
3336
- break ;
3337
- default :
3338
- num = convert_num_spec (get_arg (int ), fmt .state , spec );
3339
- break ;
3320
+ case FORMAT_STATE_NUM :
3321
+ switch (fmt .size ) {
3322
+ case 8 :
3323
+ num = get_arg (long long );
3324
+ break ;
3325
+ case 1 :
3326
+ num = convert_num_spec (get_arg (char ), fmt .size , spec );
3327
+ break ;
3328
+ case 2 :
3329
+ num = convert_num_spec (get_arg (short ), fmt .size , spec );
3330
+ break ;
3331
+ default :
3332
+ num = convert_num_spec (get_arg (int ), fmt .size , spec );
3333
+ break ;
3334
+ }
3340
3335
}
3341
3336
3342
3337
str = number (str , end , num , spec );
0 commit comments