Commit 7d8abfcb50a33aed369bbd267852cf04009c49e9

Authored by Kevin Wolf
Committed by Anthony Liguori
1 parent 9c4bab26

qemu-io: fix memory leak

qemu-io leaks the request buffer whenever the read or write function isn't
executed completely down the "normal" code path.

[hch: also fix the aio and vectored variants the same way]

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Signed-off-by: Christoph Hellwig <hch@lst.de>
Showing 1 changed file with 38 additions and 22 deletions
qemu-io.c
@@ -358,7 +358,7 @@ read_f(int argc, char **argv) @@ -358,7 +358,7 @@ read_f(int argc, char **argv)
358 358
359 if (cnt < 0) { 359 if (cnt < 0) {
360 printf("read failed: %s\n", strerror(-cnt)); 360 printf("read failed: %s\n", strerror(-cnt));
361 - return 0; 361 + goto out;
362 } 362 }
363 363
364 if (Pflag) { 364 if (Pflag) {
@@ -373,7 +373,7 @@ read_f(int argc, char **argv) @@ -373,7 +373,7 @@ read_f(int argc, char **argv)
373 } 373 }
374 374
375 if (qflag) 375 if (qflag)
376 - return 0; 376 + goto out;
377 377
378 if (vflag) 378 if (vflag)
379 dump_buffer(buf, offset, count); 379 dump_buffer(buf, offset, count);
@@ -382,6 +382,7 @@ read_f(int argc, char **argv) @@ -382,6 +382,7 @@ read_f(int argc, char **argv)
382 t2 = tsub(t2, t1); 382 t2 = tsub(t2, t1);
383 print_report("read", &t2, offset, count, total, cnt, Cflag); 383 print_report("read", &t2, offset, count, total, cnt, Cflag);
384 384
  385 +out:
385 qemu_io_free(buf); 386 qemu_io_free(buf);
386 387
387 return 0; 388 return 0;
@@ -480,7 +481,7 @@ readv_f(int argc, char **argv) @@ -480,7 +481,7 @@ readv_f(int argc, char **argv)
480 481
481 if (cnt < 0) { 482 if (cnt < 0) {
482 printf("readv failed: %s\n", strerror(-cnt)); 483 printf("readv failed: %s\n", strerror(-cnt));
483 - return 0; 484 + goto out;
484 } 485 }
485 486
486 if (Pflag) { 487 if (Pflag) {
@@ -495,7 +496,7 @@ readv_f(int argc, char **argv) @@ -495,7 +496,7 @@ readv_f(int argc, char **argv)
495 } 496 }
496 497
497 if (qflag) 498 if (qflag)
498 - return 0; 499 + goto out;
499 500
500 if (vflag) 501 if (vflag)
501 dump_buffer(buf, offset, qiov.size); 502 dump_buffer(buf, offset, qiov.size);
@@ -504,8 +505,8 @@ readv_f(int argc, char **argv) @@ -504,8 +505,8 @@ readv_f(int argc, char **argv)
504 t2 = tsub(t2, t1); 505 t2 = tsub(t2, t1);
505 print_report("read", &t2, offset, qiov.size, total, cnt, Cflag); 506 print_report("read", &t2, offset, qiov.size, total, cnt, Cflag);
506 507
  508 +out:
507 qemu_io_free(buf); 509 qemu_io_free(buf);
508 -  
509 return 0; 510 return 0;
510 } 511 }
511 512
@@ -613,16 +614,17 @@ write_f(int argc, char **argv) @@ -613,16 +614,17 @@ write_f(int argc, char **argv)
613 614
614 if (cnt < 0) { 615 if (cnt < 0) {
615 printf("write failed: %s\n", strerror(-cnt)); 616 printf("write failed: %s\n", strerror(-cnt));
616 - return 0; 617 + goto out;
617 } 618 }
618 619
619 if (qflag) 620 if (qflag)
620 - return 0; 621 + goto out;
621 622
622 /* Finally, report back -- -C gives a parsable format */ 623 /* Finally, report back -- -C gives a parsable format */
623 t2 = tsub(t2, t1); 624 t2 = tsub(t2, t1);
624 print_report("wrote", &t2, offset, count, total, cnt, Cflag); 625 print_report("wrote", &t2, offset, count, total, cnt, Cflag);
625 626
  627 +out:
626 qemu_io_free(buf); 628 qemu_io_free(buf);
627 629
628 return 0; 630 return 0;
@@ -713,18 +715,17 @@ writev_f(int argc, char **argv) @@ -713,18 +715,17 @@ writev_f(int argc, char **argv)
713 715
714 if (cnt < 0) { 716 if (cnt < 0) {
715 printf("writev failed: %s\n", strerror(-cnt)); 717 printf("writev failed: %s\n", strerror(-cnt));
716 - return 0; 718 + goto out;
717 } 719 }
718 720
719 if (qflag) 721 if (qflag)
720 - return 0; 722 + goto out;
721 723
722 /* Finally, report back -- -C gives a parsable format */ 724 /* Finally, report back -- -C gives a parsable format */
723 t2 = tsub(t2, t1); 725 t2 = tsub(t2, t1);
724 print_report("wrote", &t2, offset, qiov.size, total, cnt, Cflag); 726 print_report("wrote", &t2, offset, qiov.size, total, cnt, Cflag);
725 - 727 +out:
726 qemu_io_free(buf); 728 qemu_io_free(buf);
727 -  
728 return 0; 729 return 0;
729 } 730 }
730 731
@@ -761,18 +762,18 @@ aio_write_done(void *opaque, int ret) @@ -761,18 +762,18 @@ aio_write_done(void *opaque, int ret)
761 762
762 if (ret < 0) { 763 if (ret < 0) {
763 printf("aio_write failed: %s\n", strerror(-ret)); 764 printf("aio_write failed: %s\n", strerror(-ret));
764 - return; 765 + goto out;
765 } 766 }
766 767
767 if (ctx->qflag) { 768 if (ctx->qflag) {
768 - return; 769 + goto out;
769 } 770 }
770 771
771 /* Finally, report back -- -C gives a parsable format */ 772 /* Finally, report back -- -C gives a parsable format */
772 t2 = tsub(t2, ctx->t1); 773 t2 = tsub(t2, ctx->t1);
773 print_report("wrote", &t2, ctx->offset, ctx->qiov.size, 774 print_report("wrote", &t2, ctx->offset, ctx->qiov.size,
774 ctx->qiov.size, 1, ctx->Cflag); 775 ctx->qiov.size, 1, ctx->Cflag);
775 - 776 +out:
776 qemu_io_free(ctx->buf); 777 qemu_io_free(ctx->buf);
777 free(ctx); 778 free(ctx);
778 } 779 }
@@ -789,7 +790,7 @@ aio_read_done(void *opaque, int ret) @@ -789,7 +790,7 @@ aio_read_done(void *opaque, int ret)
789 790
790 if (ret < 0) { 791 if (ret < 0) {
791 printf("readv failed: %s\n", strerror(-ret)); 792 printf("readv failed: %s\n", strerror(-ret));
792 - return; 793 + goto out;
793 } 794 }
794 795
795 if (ctx->Pflag) { 796 if (ctx->Pflag) {
@@ -805,7 +806,7 @@ aio_read_done(void *opaque, int ret) @@ -805,7 +806,7 @@ aio_read_done(void *opaque, int ret)
805 } 806 }
806 807
807 if (ctx->qflag) { 808 if (ctx->qflag) {
808 - return; 809 + goto out;
809 } 810 }
810 811
811 if (ctx->vflag) { 812 if (ctx->vflag) {
@@ -816,7 +817,7 @@ aio_read_done(void *opaque, int ret) @@ -816,7 +817,7 @@ aio_read_done(void *opaque, int ret)
816 t2 = tsub(t2, ctx->t1); 817 t2 = tsub(t2, ctx->t1);
817 print_report("read", &t2, ctx->offset, ctx->qiov.size, 818 print_report("read", &t2, ctx->offset, ctx->qiov.size,
818 ctx->qiov.size, 1, ctx->Cflag); 819 ctx->qiov.size, 1, ctx->Cflag);
819 - 820 +out:
820 qemu_io_free(ctx->buf); 821 qemu_io_free(ctx->buf);
821 free(ctx); 822 free(ctx);
822 } 823 }
@@ -865,17 +866,20 @@ aio_read_f(int argc, char **argv) @@ -865,17 +866,20 @@ aio_read_f(int argc, char **argv)
865 ctx->vflag = 1; 866 ctx->vflag = 1;
866 break; 867 break;
867 default: 868 default:
  869 + free(ctx);
868 return command_usage(&aio_read_cmd); 870 return command_usage(&aio_read_cmd);
869 } 871 }
870 } 872 }
871 873
872 - if (optind > argc - 2) 874 + if (optind > argc - 2) {
  875 + free(ctx);
873 return command_usage(&aio_read_cmd); 876 return command_usage(&aio_read_cmd);
874 - 877 + }
875 878
876 ctx->offset = cvtnum(argv[optind]); 879 ctx->offset = cvtnum(argv[optind]);
877 if (ctx->offset < 0) { 880 if (ctx->offset < 0) {
878 printf("non-numeric length argument -- %s\n", argv[optind]); 881 printf("non-numeric length argument -- %s\n", argv[optind]);
  882 + free(ctx);
879 return 0; 883 return 0;
880 } 884 }
881 optind++; 885 optind++;
@@ -883,6 +887,7 @@ aio_read_f(int argc, char **argv) @@ -883,6 +887,7 @@ aio_read_f(int argc, char **argv)
883 if (ctx->offset & 0x1ff) { 887 if (ctx->offset & 0x1ff) {
884 printf("offset %lld is not sector aligned\n", 888 printf("offset %lld is not sector aligned\n",
885 (long long)ctx->offset); 889 (long long)ctx->offset);
  890 + free(ctx);
886 return 0; 891 return 0;
887 } 892 }
888 893
@@ -892,8 +897,11 @@ aio_read_f(int argc, char **argv) @@ -892,8 +897,11 @@ aio_read_f(int argc, char **argv)
892 gettimeofday(&ctx->t1, NULL); 897 gettimeofday(&ctx->t1, NULL);
893 acb = bdrv_aio_readv(bs, ctx->offset >> 9, &ctx->qiov, 898 acb = bdrv_aio_readv(bs, ctx->offset >> 9, &ctx->qiov,
894 ctx->qiov.size >> 9, aio_read_done, ctx); 899 ctx->qiov.size >> 9, aio_read_done, ctx);
895 - if (!acb) 900 + if (!acb) {
  901 + free(ctx->buf);
  902 + free(ctx);
896 return -EIO; 903 return -EIO;
  904 + }
897 905
898 return 0; 906 return 0;
899 } 907 }
@@ -952,16 +960,20 @@ aio_write_f(int argc, char **argv) @@ -952,16 +960,20 @@ aio_write_f(int argc, char **argv)
952 pattern = atoi(optarg); 960 pattern = atoi(optarg);
953 break; 961 break;
954 default: 962 default:
  963 + free(ctx);
955 return command_usage(&aio_write_cmd); 964 return command_usage(&aio_write_cmd);
956 } 965 }
957 } 966 }
958 967
959 - if (optind > argc - 2) 968 + if (optind > argc - 2) {
  969 + free(ctx);
960 return command_usage(&aio_write_cmd); 970 return command_usage(&aio_write_cmd);
  971 + }
961 972
962 ctx->offset = cvtnum(argv[optind]); 973 ctx->offset = cvtnum(argv[optind]);
963 if (ctx->offset < 0) { 974 if (ctx->offset < 0) {
964 printf("non-numeric length argument -- %s\n", argv[optind]); 975 printf("non-numeric length argument -- %s\n", argv[optind]);
  976 + free(ctx);
965 return 0; 977 return 0;
966 } 978 }
967 optind++; 979 optind++;
@@ -969,6 +981,7 @@ aio_write_f(int argc, char **argv) @@ -969,6 +981,7 @@ aio_write_f(int argc, char **argv)
969 if (ctx->offset & 0x1ff) { 981 if (ctx->offset & 0x1ff) {
970 printf("offset %lld is not sector aligned\n", 982 printf("offset %lld is not sector aligned\n",
971 (long long)ctx->offset); 983 (long long)ctx->offset);
  984 + free(ctx);
972 return 0; 985 return 0;
973 } 986 }
974 987
@@ -978,8 +991,11 @@ aio_write_f(int argc, char **argv) @@ -978,8 +991,11 @@ aio_write_f(int argc, char **argv)
978 gettimeofday(&ctx->t1, NULL); 991 gettimeofday(&ctx->t1, NULL);
979 acb = bdrv_aio_writev(bs, ctx->offset >> 9, &ctx->qiov, 992 acb = bdrv_aio_writev(bs, ctx->offset >> 9, &ctx->qiov,
980 ctx->qiov.size >> 9, aio_write_done, ctx); 993 ctx->qiov.size >> 9, aio_write_done, ctx);
981 - if (!acb) 994 + if (!acb) {
  995 + free(ctx->buf);
  996 + free(ctx);
982 return -EIO; 997 return -EIO;
  998 + }
983 999
984 return 0; 1000 return 0;
985 } 1001 }