Skip to content

Commit 368d749

Browse files
authored
[DFSan] Fix sscanf wrapper handling %*d (the star skips capturing). (llvm#67392)
Bug introduced in https://reviews.llvm.org/D153775
1 parent 891d511 commit 368d749

File tree

2 files changed

+150
-116
lines changed

2 files changed

+150
-116
lines changed

compiler-rt/lib/dfsan/dfsan_custom.cpp

Lines changed: 119 additions & 98 deletions
Original file line numberDiff line numberDiff line change
@@ -2246,7 +2246,8 @@ struct Formatter {
22462246
fmt_start(fmt_),
22472247
fmt_cur(fmt_),
22482248
width(-1),
2249-
num_scanned(-1) {}
2249+
num_scanned(-1),
2250+
skip(false) {}
22502251

22512252
int format() {
22522253
char *tmp_fmt = build_format_string();
@@ -2347,6 +2348,7 @@ struct Formatter {
23472348
const char *fmt_cur;
23482349
int width;
23492350
int num_scanned;
2351+
bool skip;
23502352
};
23512353

23522354
// Formats the input and propagates the input labels to the output. The output
@@ -2550,8 +2552,8 @@ static int scan_buffer(char *str, size_t size, const char *fmt,
25502552
while (*formatter.fmt_cur) {
25512553
formatter.fmt_start = formatter.fmt_cur;
25522554
formatter.width = -1;
2553-
int retval = 0;
2554-
dfsan_label l = 0;
2555+
formatter.skip = false;
2556+
int read_count = 0;
25552557
void *dst_ptr = 0;
25562558
size_t write_size = 0;
25572559
if (*formatter.fmt_cur != '%') {
@@ -2560,9 +2562,9 @@ static int scan_buffer(char *str, size_t size, const char *fmt,
25602562
for (; *(formatter.fmt_cur + 1) && *(formatter.fmt_cur + 1) != '%';
25612563
++formatter.fmt_cur) {
25622564
}
2563-
retval = formatter.scan();
2565+
read_count = formatter.scan();
25642566
dfsan_set_label(0, formatter.str_cur(),
2565-
formatter.num_written_bytes(retval));
2567+
formatter.num_written_bytes(read_count));
25662568
} else {
25672569
// Conversion directive. Consume all the characters until a conversion
25682570
// specifier or the end of the string.
@@ -2575,58 +2577,61 @@ static int scan_buffer(char *str, size_t size, const char *fmt,
25752577
case 'u':
25762578
case 'x':
25772579
case 'X':
2578-
switch (*(formatter.fmt_cur - 1)) {
2580+
if (formatter.skip) {
2581+
read_count = formatter.scan();
2582+
} else {
2583+
switch (*(formatter.fmt_cur - 1)) {
25792584
case 'h':
2580-
// Also covers the 'hh' case (since the size of the arg is still
2581-
// an int).
2582-
dst_ptr = va_arg(ap, int *);
2583-
retval = formatter.scan((int *)dst_ptr);
2584-
write_size = sizeof(int);
2585-
break;
2585+
// Also covers the 'hh' case (since the size of the arg is still
2586+
// an int).
2587+
dst_ptr = va_arg(ap, int *);
2588+
read_count = formatter.scan((int *)dst_ptr);
2589+
write_size = sizeof(int);
2590+
break;
25862591
case 'l':
2587-
if (formatter.fmt_cur - formatter.fmt_start >= 2 &&
2588-
*(formatter.fmt_cur - 2) == 'l') {
2592+
if (formatter.fmt_cur - formatter.fmt_start >= 2 &&
2593+
*(formatter.fmt_cur - 2) == 'l') {
2594+
dst_ptr = va_arg(ap, long long int *);
2595+
read_count = formatter.scan((long long int *)dst_ptr);
2596+
write_size = sizeof(long long int);
2597+
} else {
2598+
dst_ptr = va_arg(ap, long int *);
2599+
read_count = formatter.scan((long int *)dst_ptr);
2600+
write_size = sizeof(long int);
2601+
}
2602+
break;
2603+
case 'q':
25892604
dst_ptr = va_arg(ap, long long int *);
2590-
retval = formatter.scan((long long int *)dst_ptr);
2605+
read_count = formatter.scan((long long int *)dst_ptr);
25912606
write_size = sizeof(long long int);
2592-
} else {
2593-
dst_ptr = va_arg(ap, long int *);
2594-
retval = formatter.scan((long int *)dst_ptr);
2595-
write_size = sizeof(long int);
2596-
}
2597-
break;
2598-
case 'q':
2599-
dst_ptr = va_arg(ap, long long int *);
2600-
retval = formatter.scan((long long int *)dst_ptr);
2601-
write_size = sizeof(long long int);
2602-
break;
2607+
break;
26032608
case 'j':
2604-
dst_ptr = va_arg(ap, intmax_t *);
2605-
retval = formatter.scan((intmax_t *)dst_ptr);
2606-
write_size = sizeof(intmax_t);
2607-
break;
2609+
dst_ptr = va_arg(ap, intmax_t *);
2610+
read_count = formatter.scan((intmax_t *)dst_ptr);
2611+
write_size = sizeof(intmax_t);
2612+
break;
26082613
case 'z':
26092614
case 't':
2610-
dst_ptr = va_arg(ap, size_t *);
2611-
retval = formatter.scan((size_t *)dst_ptr);
2612-
write_size = sizeof(size_t);
2613-
break;
2615+
dst_ptr = va_arg(ap, size_t *);
2616+
read_count = formatter.scan((size_t *)dst_ptr);
2617+
write_size = sizeof(size_t);
2618+
break;
26142619
default:
2615-
dst_ptr = va_arg(ap, int *);
2616-
retval = formatter.scan((int *)dst_ptr);
2617-
write_size = sizeof(int);
2618-
}
2619-
// get the label associated with the string at the corresponding
2620-
// place
2621-
l = dfsan_read_label(formatter.str_cur(),
2622-
formatter.num_written_bytes(retval));
2623-
if (str_origin == nullptr)
2620+
dst_ptr = va_arg(ap, int *);
2621+
read_count = formatter.scan((int *)dst_ptr);
2622+
write_size = sizeof(int);
2623+
}
2624+
// get the label associated with the string at the corresponding
2625+
// place
2626+
dfsan_label l = dfsan_read_label(
2627+
formatter.str_cur(), formatter.num_written_bytes(read_count));
26242628
dfsan_set_label(l, dst_ptr, write_size);
2625-
else {
2629+
if (str_origin != nullptr) {
26262630
dfsan_set_label(l, dst_ptr, write_size);
2627-
size_t scan_count = formatter.num_written_bytes(retval);
2631+
size_t scan_count = formatter.num_written_bytes(read_count);
26282632
size_t size = scan_count > write_size ? write_size : scan_count;
26292633
dfsan_mem_origin_transfer(dst_ptr, formatter.str_cur(), size);
2634+
}
26302635
}
26312636
end_fmt = true;
26322637

@@ -2640,104 +2645,119 @@ static int scan_buffer(char *str, size_t size, const char *fmt,
26402645
case 'F':
26412646
case 'g':
26422647
case 'G':
2643-
if (*(formatter.fmt_cur - 1) == 'L') {
2648+
if (formatter.skip) {
2649+
read_count = formatter.scan();
2650+
} else {
2651+
if (*(formatter.fmt_cur - 1) == 'L') {
26442652
dst_ptr = va_arg(ap, long double *);
2645-
retval = formatter.scan((long double *)dst_ptr);
2653+
read_count = formatter.scan((long double *)dst_ptr);
26462654
write_size = sizeof(long double);
2647-
} else if (*(formatter.fmt_cur - 1) == 'l') {
2655+
} else if (*(formatter.fmt_cur - 1) == 'l') {
26482656
dst_ptr = va_arg(ap, double *);
2649-
retval = formatter.scan((double *)dst_ptr);
2657+
read_count = formatter.scan((double *)dst_ptr);
26502658
write_size = sizeof(double);
2651-
} else {
2659+
} else {
26522660
dst_ptr = va_arg(ap, float *);
2653-
retval = formatter.scan((float *)dst_ptr);
2661+
read_count = formatter.scan((float *)dst_ptr);
26542662
write_size = sizeof(float);
2655-
}
2656-
l = dfsan_read_label(formatter.str_cur(),
2657-
formatter.num_written_bytes(retval));
2658-
if (str_origin == nullptr)
2663+
}
2664+
dfsan_label l = dfsan_read_label(
2665+
formatter.str_cur(), formatter.num_written_bytes(read_count));
26592666
dfsan_set_label(l, dst_ptr, write_size);
2660-
else {
2667+
if (str_origin != nullptr) {
26612668
dfsan_set_label(l, dst_ptr, write_size);
2662-
size_t scan_count = formatter.num_written_bytes(retval);
2669+
size_t scan_count = formatter.num_written_bytes(read_count);
26632670
size_t size = scan_count > write_size ? write_size : scan_count;
26642671
dfsan_mem_origin_transfer(dst_ptr, formatter.str_cur(), size);
2672+
}
26652673
}
26662674
end_fmt = true;
26672675
break;
26682676

26692677
case 'c':
2670-
dst_ptr = va_arg(ap, char *);
2671-
retval = formatter.scan((char *)dst_ptr);
2672-
write_size = sizeof(char);
2673-
l = dfsan_read_label(formatter.str_cur(),
2674-
formatter.num_written_bytes(retval));
2675-
if (str_origin == nullptr)
2676-
dfsan_set_label(l, dst_ptr, write_size);
2677-
else {
2678+
if (formatter.skip) {
2679+
read_count = formatter.scan();
2680+
} else {
2681+
dst_ptr = va_arg(ap, char *);
2682+
read_count = formatter.scan((char *)dst_ptr);
2683+
write_size = sizeof(char);
2684+
dfsan_label l = dfsan_read_label(
2685+
formatter.str_cur(), formatter.num_written_bytes(read_count));
26782686
dfsan_set_label(l, dst_ptr, write_size);
2679-
size_t scan_count = formatter.num_written_bytes(retval);
2687+
if (str_origin != nullptr) {
2688+
size_t scan_count = formatter.num_written_bytes(read_count);
26802689
size_t size = scan_count > write_size ? write_size : scan_count;
26812690
dfsan_mem_origin_transfer(dst_ptr, formatter.str_cur(), size);
2691+
}
26822692
}
26832693
end_fmt = true;
26842694
break;
26852695

26862696
case 's': {
2687-
dst_ptr = va_arg(ap, char *);
2688-
retval = formatter.scan((char *)dst_ptr);
2689-
if (1 == retval) {
2697+
if (formatter.skip) {
2698+
read_count = formatter.scan();
2699+
} else {
2700+
dst_ptr = va_arg(ap, char *);
2701+
read_count = formatter.scan((char *)dst_ptr);
2702+
if (1 == read_count) {
26902703
// special case: we have parsed a single string and we need to
2691-
// update retval with the string size
2692-
retval = strlen((char *)dst_ptr);
2693-
}
2694-
if (str_origin)
2704+
// update read_count with the string size
2705+
read_count = strlen((char *)dst_ptr);
2706+
}
2707+
if (str_origin)
26952708
dfsan_mem_origin_transfer(dst_ptr, formatter.str_cur(),
2696-
formatter.num_written_bytes(retval));
2697-
va_labels++;
2698-
dfsan_mem_shadow_transfer(dst_ptr, formatter.str_cur(),
2699-
formatter.num_written_bytes(retval));
2709+
formatter.num_written_bytes(read_count));
2710+
va_labels++;
2711+
dfsan_mem_shadow_transfer(dst_ptr, formatter.str_cur(),
2712+
formatter.num_written_bytes(read_count));
2713+
}
27002714
end_fmt = true;
27012715
break;
27022716
}
27032717

27042718
case 'p':
2705-
dst_ptr = va_arg(ap, void *);
2706-
retval =
2707-
formatter.scan((int *)dst_ptr); // note: changing void* to int*
2708-
// since we need to call sizeof
2709-
write_size = sizeof(int);
2710-
2711-
l = dfsan_read_label(formatter.str_cur(),
2712-
formatter.num_written_bytes(retval));
2713-
if (str_origin == nullptr)
2719+
if (formatter.skip) {
2720+
read_count = formatter.scan();
2721+
} else {
2722+
dst_ptr = va_arg(ap, void *);
2723+
read_count =
2724+
formatter.scan((int *)dst_ptr); // note: changing void* to int*
2725+
// since we need to call sizeof
2726+
write_size = sizeof(int);
2727+
2728+
dfsan_label l = dfsan_read_label(
2729+
formatter.str_cur(), formatter.num_written_bytes(read_count));
27142730
dfsan_set_label(l, dst_ptr, write_size);
2715-
else {
2731+
if (str_origin != nullptr) {
27162732
dfsan_set_label(l, dst_ptr, write_size);
2717-
size_t scan_count = formatter.num_written_bytes(retval);
2733+
size_t scan_count = formatter.num_written_bytes(read_count);
27182734
size_t size = scan_count > write_size ? write_size : scan_count;
27192735
dfsan_mem_origin_transfer(dst_ptr, formatter.str_cur(), size);
2736+
}
27202737
}
27212738
end_fmt = true;
27222739
break;
27232740

27242741
case 'n': {
2725-
int *ptr = va_arg(ap, int *);
2726-
*ptr = (int)formatter.str_off;
2727-
va_labels++;
2728-
dfsan_set_label(0, ptr, sizeof(*ptr));
2742+
if (!formatter.skip) {
2743+
int *ptr = va_arg(ap, int *);
2744+
*ptr = (int)formatter.str_off;
2745+
*va_labels++ = 0;
2746+
dfsan_set_label(0, ptr, sizeof(*ptr));
2747+
if (str_origin != nullptr)
2748+
*str_origin++ = 0;
2749+
}
27292750
end_fmt = true;
27302751
break;
27312752
}
27322753

27332754
case '%':
2734-
retval = formatter.scan();
2755+
read_count = formatter.scan();
27352756
end_fmt = true;
27362757
break;
27372758

27382759
case '*':
2739-
formatter.width = va_arg(ap, int);
2740-
va_labels++;
2760+
formatter.skip = true;
27412761
break;
27422762

27432763
default:
@@ -2746,12 +2766,13 @@ static int scan_buffer(char *str, size_t size, const char *fmt,
27462766
}
27472767
}
27482768

2749-
if (retval < 0) {
2750-
return retval;
2769+
if (read_count < 0) {
2770+
// There was an error.
2771+
return read_count;
27512772
}
27522773

27532774
formatter.fmt_cur++;
2754-
formatter.str_off += retval;
2775+
formatter.str_off += read_count;
27552776
}
27562777

27572778
(void)va_labels; // Silence unused-but-set-parameter warning

0 commit comments

Comments
 (0)