From 7d8746340836a7efa9965a64437fc634f6898b57 Mon Sep 17 00:00:00 2001 From: Saksham Gupta Date: Mon, 9 Mar 2026 11:50:36 +0530 Subject: [PATCH 15/38] analyzer: add known function handling for atoi, atol, and atoll This patch adds kf_atoi_family to handle atoi, atol, and atoll functions in the analyzer, ensuring that the argument is checked for a valid, null-terminated string. gcc/analyzer/ChangeLog: * kf.cc (class kf_atoi_family): New class. (register_known_functions): Register atoi, atol, and atoll. gcc/testsuite/ChangeLog: * gcc.dg/analyzer/atoi-1.c: Update test coverage. Signed-off-by: Saksham Gupta --- gcc/analyzer/kf.cc | 27 ++++++++++++++++++++++++++ gcc/testsuite/gcc.dg/analyzer/atoi-1.c | 27 ++++++++++++++++++++++++++ 2 files changed, 54 insertions(+) create mode 100644 gcc/testsuite/gcc.dg/analyzer/atoi-1.c diff --git a/gcc/analyzer/kf.cc b/gcc/analyzer/kf.cc index b1ccbd6584a..69ce37272ac 100644 --- a/gcc/analyzer/kf.cc +++ b/gcc/analyzer/kf.cc @@ -833,6 +833,25 @@ private: tree m_var_decl; // could be NULL }; +class kf_atoi_family: public known_function +{ +public: + bool matches_call_types_p (const call_details &cd) const final override + { + return (cd.num_args () == 1 && cd.arg_is_pointer_p (0)); + } + + void impl_call_pre (const call_details &cd) const final override + { + /* atoi expects a valid, null-terminated string. */ + cd.check_for_null_terminated_string_arg (0, false, nullptr); + + /* atoi returns an integer, but we don't know what it is statically. + Tell the analyzer to assume it returns a generic, unknown value. */ + cd.set_any_lhs_with_defaults (); + } +}; + /* Handler for calls to "putenv". In theory we could try to model the state of the environment variables @@ -2289,6 +2308,10 @@ register_known_functions (known_function_manager &kfm, /* Known builtins and C standard library functions the analyzer has known functions for. */ { + kfm.add ("atoi", std::make_unique ()); + kfm.add ("atol", std::make_unique ()); + kfm.add ("atoll", std::make_unique ()); + kfm.add ("alloca", std::make_unique ()); kfm.add ("__builtin_alloca", std::make_unique ()); kfm.add ("calloc", std::make_unique ()); @@ -2388,6 +2411,10 @@ register_known_functions (known_function_manager &kfm, from etc for the C spellings of these headers (e.g. ), so we must match against these too. */ { + kfm.add_std_ns ("atoi", std::make_unique ()); + kfm.add_std_ns ("atol", std::make_unique ()); + kfm.add_std_ns ("atoll", std::make_unique ()); + kfm.add_std_ns ("malloc", std::make_unique ()); kfm.add_std_ns ("free", std::make_unique ()); kfm.add_std_ns ("realloc", std::make_unique ()); diff --git a/gcc/testsuite/gcc.dg/analyzer/atoi-1.c b/gcc/testsuite/gcc.dg/analyzer/atoi-1.c new file mode 100644 index 00000000000..5b008bf9b73 --- /dev/null +++ b/gcc/testsuite/gcc.dg/analyzer/atoi-1.c @@ -0,0 +1,27 @@ +#include + +void test_valid_atoi(void) { + int val = atoi("123"); /* Should be fine. */ +} + +void test_uninitialized_atoi(void) { + char buf[10]; + int val = atoi(buf); /* { dg-warning "use of uninitialized value" } */ +} + +void test_atoi_no_lhs(void) { + atoi("123"); /* Should be fine, shouldn't crash. */ +} + +void test_unterminated_atoi(void) { + char buf[3] = {'1', '2', '3'}; + int val = atoi(buf); /* { dg-warning "over-read" } */ +} + +void test_valid_atol(void) { + long val = atol("123"); /* Should be fine. */ +} + +void test_valid_atoll(void) { + long long val = atoll("123"); /* Should be fine. */ +} -- 2.49.0