From 585d0700c7dbbc3cf032ad2e710d48eda85dd7ce Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Sat, 28 Mar 2020 20:58:34 -0500 Subject: avoid out-of-bounds read after invalid %cpu conversion In the case where no CPU number is given, skipping a character of padding actually skips the null terminator, causing further iterations through the loop to read out of bounds. Have sscanf() return the number of characters read, instead of reconstructing it from the CPU number. This was observed as a failure in test 024-cpu-usage-invalid-cpu. --- src/print_cpu_usage.c | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/print_cpu_usage.c b/src/print_cpu_usage.c index 979e082..abf3481 100644 --- a/src/print_cpu_usage.c +++ b/src/print_cpu_usage.c @@ -183,7 +183,8 @@ void print_cpu_usage(yajl_gen json_gen, char *buffer, const char *format, const #if defined(__linux__) else if (BEGINS_WITH(walk + 1, "cpu")) { int number = -1; - sscanf(walk + 1, "cpu%d", &number); + int length = strlen("cpu"); + sscanf(walk + 1, "cpu%d%n", &number, &length); if (number == -1) { fprintf(stderr, "i3status: provided CPU number cannot be parsed\n"); } else if (number >= cpu_count) { @@ -194,13 +195,7 @@ void print_cpu_usage(yajl_gen json_gen, char *buffer, const char *format, const int cpu_diff_usage = (cpu_diff_total ? (1000 * (cpu_diff_total - cpu_diff_idle) / cpu_diff_total + 5) / 10 : 0); outwalk += sprintf(outwalk, "%02d%s", cpu_diff_usage, pct_mark); } - int padding = 1; - int step = 10; - while (step <= number) { - step *= 10; - padding++; - } - walk += strlen("cpu") + padding; + walk += length; } #endif else { -- cgit v1.2.3