diff options
author | Samuel Holland <samuel@sholland.org> | 2020-03-28 20:58:34 -0500 |
---|---|---|
committer | Samuel Holland <samuel@sholland.org> | 2020-03-28 21:02:02 -0500 |
commit | 585d0700c7dbbc3cf032ad2e710d48eda85dd7ce (patch) | |
tree | 16f1d3922cc64132bd9d1b2bf95507265841273d | |
parent | 3374e1605d718816d08ba91721aa82ec73086b9d (diff) |
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.
-rw-r--r-- | src/print_cpu_usage.c | 11 |
1 files changed, 3 insertions, 8 deletions
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 { |