From nobody Mon Apr 6 22:55:56 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id C8046C433F5 for ; Thu, 6 Oct 2022 17:12:16 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231699AbiJFRMO (ORCPT ); Thu, 6 Oct 2022 13:12:14 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:48590 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231567AbiJFRMG (ORCPT ); Thu, 6 Oct 2022 13:12:06 -0400 Received: from mail-pg1-x549.google.com (mail-pg1-x549.google.com [IPv6:2607:f8b0:4864:20::549]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id F271DA98D2 for ; Thu, 6 Oct 2022 10:12:00 -0700 (PDT) Received: by mail-pg1-x549.google.com with SMTP id 69-20020a630148000000b0043bbb38f75bso1464057pgb.6 for ; Thu, 06 Oct 2022 10:12:00 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=5dKSwh7+qx3XoQgeIzt1baz66Fx4CxMFyvLvfA9g4zQ=; b=Lmb4FRH/8NwdJTQqNP/Z7GuAmBufmUr0IfcW+8J8m1PuxV7d8le14ZtRfVzWt+jX6K 9gg8eEFCktXBPzTLoHFFYB7Kh/cljJKqb++gSqaqAHmaOkEp02S/H9FrkbJSJyK4zAtK Wow73n0y9nTKNKRscrinw5dTabMriKID6AwOpebsnjwE9Kk4yK5h0EHLpV7WbLCSWxd3 n5lUSRdKDAb4+ik1Y9mEyb2R8IjoMpKwYoEuKvc0qNorGm5unEJEF0T1+P5IzItJOSY4 ZU+sF8YkDQTIp4NsxRf6idJ1kbujaP9T6EcJ1J3FWRXPoR/7iMJ/rl4XH4BegtkIL6mW QLog== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=5dKSwh7+qx3XoQgeIzt1baz66Fx4CxMFyvLvfA9g4zQ=; b=PtkcwhEpmES45wkqdlaX71fxE6fDkp1zPxOGNZTiYWkESkbvJviG/VwPpfYEBtM17i 5aSlezFiTVCsmyI9dZ2hkNZwCOHNkVnZXdw02skg7MQJSFxwbNbC4KmDu+olZm+bZny+ vlRo7TCMiB5cDKwmvUUKG9sTETxDzYoK71keJNFak2GHhRnzVBhQkZvKBkNhuhX4IvCY WKZGDgFrZOwy9VoIeW/kQfdtFx/9qGNLWN0qMjgDd6wsyyc6KVMyKBobUa3ZwB3kOC8f 8JtGFbT4WVnRZ5HTRkzx61A007j8mufCzbqQr61rhs4F1nNp5rSuAA+2fO4QyO1k7L3X 3Oxg== X-Gm-Message-State: ACrzQf0E9PqL74rBep6CY+dEXYFVTsp3E5gLzVHR3oT4Zz95W313VD2e 9z205UMoyeX1beaVrv0wL5K1q5FnFFoE X-Google-Smtp-Source: AMsMyM6GmhR/uOI0BPw9RRhimHfc4pi1CX3QkLp4hPonViI3HkPbI/W5yyLXZ+1Y0ap9wuPwb226xDT/f/Qp X-Received: from vipin.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:479f]) (user=vipinsh job=sendgmr) by 2002:a05:6a00:2292:b0:547:5bd7:8966 with SMTP id f18-20020a056a00229200b005475bd78966mr789571pfe.62.1665076319953; Thu, 06 Oct 2022 10:11:59 -0700 (PDT) Date: Thu, 6 Oct 2022 10:11:31 -0700 In-Reply-To: <20221006171133.372359-1-vipinsh@google.com> Mime-Version: 1.0 References: <20221006171133.372359-1-vipinsh@google.com> X-Mailer: git-send-email 2.38.0.rc1.362.ged0d419d3c-goog Message-ID: <20221006171133.372359-4-vipinsh@google.com> Subject: [PATCH v4 3/4] KVM: selftests: Add atoi_paranoid() to catch errors missed by atoi() From: Vipin Sharma To: seanjc@google.com, pbonzini@redhat.com, dmatlack@google.com Cc: andrew.jones@linux.dev, kvm@vger.kernel.org, linux-kernel@vger.kernel.org, Vipin Sharma Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" atoi() doesn't detect errors. There is no way to know that a 0 return is correct conversion or due to an error. Introduce atoi_paranoid() to detect errors and provide correct conversion. Replace all atoi() calls with atoi_paranoid(). Signed-off-by: Vipin Sharma Suggested-by: David Matlack Suggested-by: Sean Christopherson --- .../testing/selftests/kvm/aarch64/arch_timer.c | 8 ++++---- tools/testing/selftests/kvm/aarch64/vgic_irq.c | 6 +++--- .../selftests/kvm/access_tracking_perf_test.c | 2 +- .../testing/selftests/kvm/demand_paging_test.c | 2 +- .../selftests/kvm/dirty_log_perf_test.c | 8 ++++---- .../testing/selftests/kvm/include/test_util.h | 2 ++ .../selftests/kvm/kvm_page_table_test.c | 2 +- tools/testing/selftests/kvm/lib/test_util.c | 18 ++++++++++++++++++ .../selftests/kvm/max_guest_memory_test.c | 6 +++--- .../kvm/memslot_modification_stress_test.c | 4 ++-- .../testing/selftests/kvm/memslot_perf_test.c | 10 +++++----- .../selftests/kvm/set_memory_region_test.c | 2 +- .../selftests/kvm/x86_64/nx_huge_pages_test.c | 4 ++-- 13 files changed, 47 insertions(+), 27 deletions(-) diff --git a/tools/testing/selftests/kvm/aarch64/arch_timer.c b/tools/testi= ng/selftests/kvm/aarch64/arch_timer.c index 574eb73f0e90..251e7ff04883 100644 --- a/tools/testing/selftests/kvm/aarch64/arch_timer.c +++ b/tools/testing/selftests/kvm/aarch64/arch_timer.c @@ -414,7 +414,7 @@ static bool parse_args(int argc, char *argv[]) while ((opt =3D getopt(argc, argv, "hn:i:p:m:")) !=3D -1) { switch (opt) { case 'n': - test_args.nr_vcpus =3D atoi(optarg); + test_args.nr_vcpus =3D atoi_paranoid(optarg); if (test_args.nr_vcpus <=3D 0) { pr_info("Positive value needed for -n\n"); goto err; @@ -425,21 +425,21 @@ static bool parse_args(int argc, char *argv[]) } break; case 'i': - test_args.nr_iter =3D atoi(optarg); + test_args.nr_iter =3D atoi_paranoid(optarg); if (test_args.nr_iter <=3D 0) { pr_info("Positive value needed for -i\n"); goto err; } break; case 'p': - test_args.timer_period_ms =3D atoi(optarg); + test_args.timer_period_ms =3D atoi_paranoid(optarg); if (test_args.timer_period_ms <=3D 0) { pr_info("Positive value needed for -p\n"); goto err; } break; case 'm': - test_args.migration_freq_ms =3D atoi(optarg); + test_args.migration_freq_ms =3D atoi_paranoid(optarg); if (test_args.migration_freq_ms < 0) { pr_info("0 or positive value needed for -m\n"); goto err; diff --git a/tools/testing/selftests/kvm/aarch64/vgic_irq.c b/tools/testing= /selftests/kvm/aarch64/vgic_irq.c index 17417220a083..ae90b718070a 100644 --- a/tools/testing/selftests/kvm/aarch64/vgic_irq.c +++ b/tools/testing/selftests/kvm/aarch64/vgic_irq.c @@ -824,16 +824,16 @@ int main(int argc, char **argv) while ((opt =3D getopt(argc, argv, "hn:e:l:")) !=3D -1) { switch (opt) { case 'n': - nr_irqs =3D atoi(optarg); + nr_irqs =3D atoi_paranoid(optarg); if (nr_irqs > 1024 || nr_irqs % 32) help(argv[0]); break; case 'e': - eoi_split =3D (bool)atoi(optarg); + eoi_split =3D (bool)atoi_paranoid(optarg); default_args =3D false; break; case 'l': - level_sensitive =3D (bool)atoi(optarg); + level_sensitive =3D (bool)atoi_paranoid(optarg); default_args =3D false; break; case 'h': diff --git a/tools/testing/selftests/kvm/access_tracking_perf_test.c b/tool= s/testing/selftests/kvm/access_tracking_perf_test.c index 76c583a07ea2..c6bcc5301e2c 100644 --- a/tools/testing/selftests/kvm/access_tracking_perf_test.c +++ b/tools/testing/selftests/kvm/access_tracking_perf_test.c @@ -368,7 +368,7 @@ int main(int argc, char *argv[]) params.vcpu_memory_bytes =3D parse_size(optarg); break; case 'v': - params.nr_vcpus =3D atoi(optarg); + params.nr_vcpus =3D atoi_paranoid(optarg); break; case 'o': overlap_memory_access =3D true; diff --git a/tools/testing/selftests/kvm/demand_paging_test.c b/tools/testi= ng/selftests/kvm/demand_paging_test.c index 779ae54f89c4..82597fb04146 100644 --- a/tools/testing/selftests/kvm/demand_paging_test.c +++ b/tools/testing/selftests/kvm/demand_paging_test.c @@ -427,7 +427,7 @@ int main(int argc, char *argv[]) p.src_type =3D parse_backing_src_type(optarg); break; case 'v': - nr_vcpus =3D atoi(optarg); + nr_vcpus =3D atoi_paranoid(optarg); TEST_ASSERT(nr_vcpus > 0 && nr_vcpus <=3D max_vcpus, "Invalid number of vcpus, must be between 1 and %d", max_vcpus); break; diff --git a/tools/testing/selftests/kvm/dirty_log_perf_test.c b/tools/test= ing/selftests/kvm/dirty_log_perf_test.c index 5bb6954b2358..ecda802b78ff 100644 --- a/tools/testing/selftests/kvm/dirty_log_perf_test.c +++ b/tools/testing/selftests/kvm/dirty_log_perf_test.c @@ -416,7 +416,7 @@ int main(int argc, char *argv[]) run_vcpus_while_disabling_dirty_logging =3D true; break; case 'f': - p.wr_fract =3D atoi(optarg); + p.wr_fract =3D atoi_paranoid(optarg); TEST_ASSERT(p.wr_fract >=3D 1, "Write fraction cannot be less than one"); break; @@ -427,7 +427,7 @@ int main(int argc, char *argv[]) help(argv[0]); break; case 'i': - p.iterations =3D atoi(optarg); + p.iterations =3D atoi_paranoid(optarg); break; case 'm': guest_modes_cmdline(optarg); @@ -445,12 +445,12 @@ int main(int argc, char *argv[]) p.backing_src =3D parse_backing_src_type(optarg); break; case 'v': - nr_vcpus =3D atoi(optarg); + nr_vcpus =3D atoi_paranoid(optarg); TEST_ASSERT(nr_vcpus > 0 && nr_vcpus <=3D max_vcpus, "Invalid number of vcpus, must be between 1 and %d", max_vcpus); break; case 'x': - p.slots =3D atoi(optarg); + p.slots =3D atoi_paranoid(optarg); break; default: help(argv[0]); diff --git a/tools/testing/selftests/kvm/include/test_util.h b/tools/testin= g/selftests/kvm/include/test_util.h index befc754ce9b3..feae42863759 100644 --- a/tools/testing/selftests/kvm/include/test_util.h +++ b/tools/testing/selftests/kvm/include/test_util.h @@ -152,4 +152,6 @@ static inline void *align_ptr_up(void *x, size_t size) return (void *)align_up((unsigned long)x, size); } =20 +int atoi_paranoid(const char *num_str); + #endif /* SELFTEST_KVM_TEST_UTIL_H */ diff --git a/tools/testing/selftests/kvm/kvm_page_table_test.c b/tools/test= ing/selftests/kvm/kvm_page_table_test.c index f42c6ac6d71d..ea7feb69bb88 100644 --- a/tools/testing/selftests/kvm/kvm_page_table_test.c +++ b/tools/testing/selftests/kvm/kvm_page_table_test.c @@ -461,7 +461,7 @@ int main(int argc, char *argv[]) p.test_mem_size =3D parse_size(optarg); break; case 'v': - nr_vcpus =3D atoi(optarg); + nr_vcpus =3D atoi_paranoid(optarg); TEST_ASSERT(nr_vcpus > 0 && nr_vcpus <=3D max_vcpus, "Invalid number of vcpus, must be between 1 and %d", max_vcpus); break; diff --git a/tools/testing/selftests/kvm/lib/test_util.c b/tools/testing/se= lftests/kvm/lib/test_util.c index 6d23878bbfe1..8cce52ee139f 100644 --- a/tools/testing/selftests/kvm/lib/test_util.c +++ b/tools/testing/selftests/kvm/lib/test_util.c @@ -334,3 +334,21 @@ long get_run_delay(void) =20 return val[1]; } + +int atoi_paranoid(const char *num_str) +{ + int num; + char *end_ptr; + + errno =3D 0; + num =3D (int)strtol(num_str, &end_ptr, 10); + TEST_ASSERT(!errno, "strtol(\"%s\") failed", num_str); + TEST_ASSERT(num_str !=3D end_ptr, + "strtol(\"%s\") didn't find any valid number.\n", num_str); + TEST_ASSERT( + *end_ptr =3D=3D '\0', + "strtol(\"%s\") failed to parse trailing characters \"%s\".\n", + num_str, end_ptr); + + return num; +} diff --git a/tools/testing/selftests/kvm/max_guest_memory_test.c b/tools/te= sting/selftests/kvm/max_guest_memory_test.c index 9a6e4f3ad6b5..1595b73dc09a 100644 --- a/tools/testing/selftests/kvm/max_guest_memory_test.c +++ b/tools/testing/selftests/kvm/max_guest_memory_test.c @@ -193,15 +193,15 @@ int main(int argc, char *argv[]) while ((opt =3D getopt(argc, argv, "c:h:m:s:H")) !=3D -1) { switch (opt) { case 'c': - nr_vcpus =3D atoi(optarg); + nr_vcpus =3D atoi_paranoid(optarg); TEST_ASSERT(nr_vcpus > 0, "number of vcpus must be >0"); break; case 'm': - max_mem =3D atoi(optarg) * size_1gb; + max_mem =3D atoi_paranoid(optarg) * size_1gb; TEST_ASSERT(max_mem > 0, "memory size must be >0"); break; case 's': - slot_size =3D atoi(optarg) * size_1gb; + slot_size =3D atoi_paranoid(optarg) * size_1gb; TEST_ASSERT(slot_size > 0, "slot size must be >0"); break; case 'H': diff --git a/tools/testing/selftests/kvm/memslot_modification_stress_test.c= b/tools/testing/selftests/kvm/memslot_modification_stress_test.c index 6ee7e1dde404..865276993ffb 100644 --- a/tools/testing/selftests/kvm/memslot_modification_stress_test.c +++ b/tools/testing/selftests/kvm/memslot_modification_stress_test.c @@ -166,7 +166,7 @@ int main(int argc, char *argv[]) guest_percpu_mem_size =3D parse_size(optarg); break; case 'v': - nr_vcpus =3D atoi(optarg); + nr_vcpus =3D atoi_paranoid(optarg); TEST_ASSERT(nr_vcpus > 0 && nr_vcpus <=3D max_vcpus, "Invalid number of vcpus, must be between 1 and %d", max_vcpus); @@ -175,7 +175,7 @@ int main(int argc, char *argv[]) p.partition_vcpu_memory_access =3D false; break; case 'i': - p.nr_memslot_modifications =3D atoi(optarg); + p.nr_memslot_modifications =3D atoi_paranoid(optarg); break; case 'h': default: diff --git a/tools/testing/selftests/kvm/memslot_perf_test.c b/tools/testin= g/selftests/kvm/memslot_perf_test.c index 44995446d942..4bae9e3f5ca1 100644 --- a/tools/testing/selftests/kvm/memslot_perf_test.c +++ b/tools/testing/selftests/kvm/memslot_perf_test.c @@ -885,21 +885,21 @@ static bool parse_args(int argc, char *argv[], map_unmap_verify =3D true; break; case 's': - targs->nslots =3D atoi(optarg); + targs->nslots =3D atoi_paranoid(optarg); if (targs->nslots <=3D 0 && targs->nslots !=3D -1) { pr_info("Slot count cap has to be positive or -1 for no cap\n"); return false; } break; case 'f': - targs->tfirst =3D atoi(optarg); + targs->tfirst =3D atoi_paranoid(optarg); if (targs->tfirst < 0) { pr_info("First test to run has to be non-negative\n"); return false; } break; case 'e': - targs->tlast =3D atoi(optarg); + targs->tlast =3D atoi_paranoid(optarg); if (targs->tlast < 0 || targs->tlast >=3D NTESTS) { pr_info("Last test to run has to be non-negative and less than %zu\n", NTESTS); @@ -907,14 +907,14 @@ static bool parse_args(int argc, char *argv[], } break; case 'l': - targs->seconds =3D atoi(optarg); + targs->seconds =3D atoi_paranoid(optarg); if (targs->seconds < 0) { pr_info("Test length in seconds has to be non-negative\n"); return false; } break; case 'r': - targs->runs =3D atoi(optarg); + targs->runs =3D atoi_paranoid(optarg); if (targs->runs <=3D 0) { pr_info("Runs per test has to be positive\n"); return false; diff --git a/tools/testing/selftests/kvm/set_memory_region_test.c b/tools/t= esting/selftests/kvm/set_memory_region_test.c index 0d55f508d595..c366949c8362 100644 --- a/tools/testing/selftests/kvm/set_memory_region_test.c +++ b/tools/testing/selftests/kvm/set_memory_region_test.c @@ -407,7 +407,7 @@ int main(int argc, char *argv[]) =20 #ifdef __x86_64__ if (argc > 1) - loops =3D atoi(argv[1]); + loops =3D atoi_paranoid(argv[1]); else loops =3D 10; =20 diff --git a/tools/testing/selftests/kvm/x86_64/nx_huge_pages_test.c b/tool= s/testing/selftests/kvm/x86_64/nx_huge_pages_test.c index 59ffe7fd354f..354b6902849c 100644 --- a/tools/testing/selftests/kvm/x86_64/nx_huge_pages_test.c +++ b/tools/testing/selftests/kvm/x86_64/nx_huge_pages_test.c @@ -241,10 +241,10 @@ int main(int argc, char **argv) while ((opt =3D getopt(argc, argv, "hp:t:r")) !=3D -1) { switch (opt) { case 'p': - reclaim_period_ms =3D atoi(optarg); + reclaim_period_ms =3D atoi_paranoid(optarg); break; case 't': - token =3D atoi(optarg); + token =3D atoi_paranoid(optarg); break; case 'r': reboot_permissions =3D true; --=20 2.38.0.rc1.362.ged0d419d3c-goog