Commit cf070d7ec0b8fb21faa9a630ed5cc66f90844a08
Committed by
Anthony Liguori
1 parent
a7824a88
qemu-io: reject invalid pattern
Replace the use of atoi which is used for pattern parsing currently with strtol. Atoi won't parse sedecimal pattern values (it always returns 0), but qemu-iotests use such pattern values. Also reject every pattern that is not a unsigned char as we pass the pattern to memset which expect a bye value (despite having the pattern argument declared as int). Based on an earlier patch by Stefan Weil which did not include the error handling. Signed-off-by: Christoph Hellwig <hch@lst.de> Reported-by: Stefan Weil <weil@mail.berlios.de> Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
Showing
1 changed file
with
38 additions
and
6 deletions
qemu-io.c
| @@ -26,6 +26,26 @@ static BlockDriverState *bs; | @@ -26,6 +26,26 @@ static BlockDriverState *bs; | ||
| 26 | static int misalign; | 26 | static int misalign; |
| 27 | 27 | ||
| 28 | /* | 28 | /* |
| 29 | + * Parse the pattern argument to various sub-commands. | ||
| 30 | + * | ||
| 31 | + * Because the pattern is used as an argument to memset it must evaluate | ||
| 32 | + * to an unsigned integer that fits into a single byte. | ||
| 33 | + */ | ||
| 34 | +static int parse_pattern(const char *arg) | ||
| 35 | +{ | ||
| 36 | + char *endptr = NULL; | ||
| 37 | + long pattern; | ||
| 38 | + | ||
| 39 | + pattern = strtol(arg, &endptr, 0); | ||
| 40 | + if (pattern < 0 || pattern > UCHAR_MAX || *endptr != '\0') { | ||
| 41 | + printf("%s is not a valid pattern byte\n", arg); | ||
| 42 | + return -1; | ||
| 43 | + } | ||
| 44 | + | ||
| 45 | + return pattern; | ||
| 46 | +} | ||
| 47 | + | ||
| 48 | +/* | ||
| 29 | * Memory allocation helpers. | 49 | * Memory allocation helpers. |
| 30 | * | 50 | * |
| 31 | * Make sure memory is aligned by default, or purposefully misaligned if | 51 | * Make sure memory is aligned by default, or purposefully misaligned if |
| @@ -304,7 +324,9 @@ read_f(int argc, char **argv) | @@ -304,7 +324,9 @@ read_f(int argc, char **argv) | ||
| 304 | break; | 324 | break; |
| 305 | case 'P': | 325 | case 'P': |
| 306 | Pflag = 1; | 326 | Pflag = 1; |
| 307 | - pattern = atoi(optarg); | 327 | + pattern = parse_pattern(optarg); |
| 328 | + if (pattern < 0) | ||
| 329 | + return 0; | ||
| 308 | break; | 330 | break; |
| 309 | case 'q': | 331 | case 'q': |
| 310 | qflag = 1; | 332 | qflag = 1; |
| @@ -469,7 +491,9 @@ readv_f(int argc, char **argv) | @@ -469,7 +491,9 @@ readv_f(int argc, char **argv) | ||
| 469 | break; | 491 | break; |
| 470 | case 'P': | 492 | case 'P': |
| 471 | Pflag = 1; | 493 | Pflag = 1; |
| 472 | - pattern = atoi(optarg); | 494 | + pattern = parse_pattern(optarg); |
| 495 | + if (pattern < 0) | ||
| 496 | + return 0; | ||
| 473 | break; | 497 | break; |
| 474 | case 'q': | 498 | case 'q': |
| 475 | qflag = 1; | 499 | qflag = 1; |
| @@ -594,7 +618,9 @@ write_f(int argc, char **argv) | @@ -594,7 +618,9 @@ write_f(int argc, char **argv) | ||
| 594 | pflag = 1; | 618 | pflag = 1; |
| 595 | break; | 619 | break; |
| 596 | case 'P': | 620 | case 'P': |
| 597 | - pattern = atoi(optarg); | 621 | + pattern = parse_pattern(optarg); |
| 622 | + if (pattern < 0) | ||
| 623 | + return 0; | ||
| 598 | break; | 624 | break; |
| 599 | case 'q': | 625 | case 'q': |
| 600 | qflag = 1; | 626 | qflag = 1; |
| @@ -721,7 +747,9 @@ writev_f(int argc, char **argv) | @@ -721,7 +747,9 @@ writev_f(int argc, char **argv) | ||
| 721 | qflag = 1; | 747 | qflag = 1; |
| 722 | break; | 748 | break; |
| 723 | case 'P': | 749 | case 'P': |
| 724 | - pattern = atoi(optarg); | 750 | + pattern = parse_pattern(optarg); |
| 751 | + if (pattern < 0) | ||
| 752 | + return 0; | ||
| 725 | break; | 753 | break; |
| 726 | default: | 754 | default: |
| 727 | return command_usage(&writev_cmd); | 755 | return command_usage(&writev_cmd); |
| @@ -895,7 +923,9 @@ aio_read_f(int argc, char **argv) | @@ -895,7 +923,9 @@ aio_read_f(int argc, char **argv) | ||
| 895 | break; | 923 | break; |
| 896 | case 'P': | 924 | case 'P': |
| 897 | ctx->Pflag = 1; | 925 | ctx->Pflag = 1; |
| 898 | - ctx->pattern = atoi(optarg); | 926 | + ctx->pattern = parse_pattern(optarg); |
| 927 | + if (ctx->pattern < 0) | ||
| 928 | + return 0; | ||
| 899 | break; | 929 | break; |
| 900 | case 'q': | 930 | case 'q': |
| 901 | ctx->qflag = 1; | 931 | ctx->qflag = 1; |
| @@ -995,7 +1025,9 @@ aio_write_f(int argc, char **argv) | @@ -995,7 +1025,9 @@ aio_write_f(int argc, char **argv) | ||
| 995 | ctx->qflag = 1; | 1025 | ctx->qflag = 1; |
| 996 | break; | 1026 | break; |
| 997 | case 'P': | 1027 | case 'P': |
| 998 | - pattern = atoi(optarg); | 1028 | + pattern = parse_pattern(optarg); |
| 1029 | + if (pattern < 0) | ||
| 1030 | + return 0; | ||
| 999 | break; | 1031 | break; |
| 1000 | default: | 1032 | default: |
| 1001 | free(ctx); | 1033 | free(ctx); |