On Mon, 2026-03-09 at 12:09 +0530, Saksham Gupta wrote:
> Hi David,
> 
> Following your suggestion to look into kf.cc, I noticed that the
> analyzer
> didn't have known function handlers for atoi or atol.
> 
> I have implemented a kf_atoi class that verifies the incoming
> argument is a
> valid, null-terminated string and sets the LHS to a generic unknown
> value.
> I also added a regression test (atoi-1.c) which successfully flags
> uninitialized buffers passed to atoi.
> 
> I've attached the patch (with the Signed-off-by tag and ChangeLog).
> I've
> run the DejaGnu test suite on this (make check-gcc
> RUNTESTFLAGS="analyzer.exp=atoi-1.c") and it passes with zero
> regressions.

Thanks for the patch!  The kf stuff is a major part of the CPython API
project, so it's good to see you getting familiar with it.

Overall, the patch looks great, but I have a few comments:

> diff --git a/gcc/analyzer/kf.cc b/gcc/analyzer/kf.cc
> index b1ccbd6584a..bc625682717 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: public known_function

How about naming this "kf_atoi_family" since it handles various
functions, not just "atoi" specifically.

> +{
> +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 ();
> +  }
> +};

Looks correct.

>     In theory we could try to model the state of the environment variables
> @@ -2289,6 +2308,9 @@ 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<kf_atoi> ());
> +    kfm.add ("atol", std::make_unique<kf_atoi> ());

We could do "atoll" here for good measure as well.


> @@ -2388,6 +2410,9 @@ register_known_functions (known_function_manager &kfm,
>       from <cstdlib> etc for the C spellings of these headers (e.g. 
> <stdlib.h>),
>       so we must match against these too.  */
>    {
> +    kfm.add_std_ns ("atoi", std::make_unique<kf_atoi> ());
> +    kfm.add_std_ns ("atol", std::make_unique<kf_atoi> ());

Likewise here.

> 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..67d7b103457
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/analyzer/atoi-1.c
> @@ -0,0 +1,11 @@
> +/* { dg-additional-options "-Wno-analyzer-too-complex" } */

Do we need -Wno-analyzer-too-complex here, or was this due to
copy&pasting from another example?

> +#include <stdlib.h>
> +
> +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" } */
> +}

This is good, but please add more test coverage:

* a call to atoi for which the return value isn't taken
(set_any_lhs_with_defaults handles this, but in the past I've had
crashes in kf handlers due to assuming that there is an LHS to write
the result to).

* a call to atoi with an unterminated buffer

* calls to atol and atoll to check that they're wired up.

You should probably get familiar with how to do a bootstrap build of
GCC.  Have you tried this yet?  Let us know if you need a more powerful
machine; see e.g. https://portal.cfarm.net/  or want some pointers on
how to do this.

One other thing to mention - right now we're in feature freeze for GCC
16, trying to focus on stabilizing for the release - we call this
"stage 4" of the release cycle.  Hence I plan to wait before actually
pushing the patch.  Hopefully we'll transition to stage 1 of the GCC 17
release cycle sometime next month (when we're open to new features).

Hope this all makes sense; thanks again for the patch
Dave

Reply via email to