> On Feb 17, 2026, at 16:25, David Malcolm <[email protected]> wrote:
> 
> On Tue, 2026-02-17 at 20:04 +0000, Qing Zhao wrote:
>> 
>> 
>>> On Feb 17, 2026, at 13:26, David Malcolm <[email protected]>
>>> wrote:
>>> 
>>> On Tue, 2026-02-17 at 12:24 -0500, David Malcolm wrote:
>>>> On Tue, 2026-02-17 at 16:33 +0000, Qing Zhao wrote:
>>>>> Hi, David,
>>>>> 
>>>>> I am working on PR96503 right now, and the initial
>>>>> implementation
>>>>> has
>>>>> some regression in analyzer as show from the following small
>>>>> testing
>>>>> case:
>>>>> $ cat t.c
>>>>> #include <stdlib.h>
>>>>> #include <stdio.h>
>>>>> #include <stdint.h>
>>>>> 
>>>>> /* Tests with constant buffer sizes.  */
>>>>> 
>>>>> void test_2 (void)
>>>>> {
>>>>>   int32_t *ptr = (int32_t *) malloc (21 * sizeof (int16_t)); /*
>>>>> {
>>>>> dg-
>>>>> line malloc2 } */
>>>>>   free (ptr);
>>>>> 
>>>>>   /* { dg-warning "allocated buffer size is not a multiple of
>>>>> the
>>>>> pointee's size \\\[CWE-131\\\]" "warning" { target *-*-* }
>>>>> malloc2
>>>>> }
>>>>> */
>>>>>   /* { dg-message "42 bytes" "note" { target *-*-* } malloc2 }
>>>>> */
>>>>>   /* { dg-message "'int32_t \\*' (\\\{aka '(long )?int
>>>>> \\*'\\\})?
>>>>> here; 'sizeof \\(int32_t (\\\{aka (long )?int\\\})?\\)' is '4'"
>>>>> "note" { target c } malloc2 } */
>>>>>   /* { dg-message "'int32_t\\*' (\\\{aka '(long )?int\\*'\\\})?
>>>>> here;
>>>>> 'sizeof \\(int32_t (\\\{aka (long )?int\\\})?\\)' is '4'"
>>>>> "note" {
>>>>> target c++ } malloc2 } */
>>>>> }
>>>>> 
>>>>> ****Without my change, the IR for the above is:
>>>>> 
>>>>> void test_2 ()
>>>>> {
>>>>>   int32_t * ptr;
>>>>> 
>>>>>   ptr = malloc (42);
>>>>>   free (ptr);
>>>>> }
>>>>> 
>>>>> And when compiled with "-fdiagnostics-plain-output -fanalyzer -
>>>>> Wanalyzer-too-complex -Wanalyzer-symbol-too-complex -S”:t.c: In
>>>>> function ‘test_2’:
>>>>> t.c:9:30: warning: allocated buffer size is not a multiple of
>>>>> the
>>>>> pointee's size [CWE-131] [-Wanalyzer-allocation-size]
>>>>> t.c:9:30: note: (1) allocated 42 bytes here
>>>>> t.c:9:30: note: (2) assigned to ‘int32_t *’ {aka ‘int *’} here;
>>>>> ‘sizeof (int32_t {aka int})’ is ‘4’
>>>>> 
>>>>> **** with my change, the IR for the above is:
>>>>> void test_2 ()
>>>>> {
>>>>>   int32_t * ptr;
>>>>> 
>>>>>   _1 = malloc (42);
>>>>>   ptr = .ACCESS_WITH_SIZE (_1, 42, 4B, 1);
>>>>>   free (ptr);
>>>>> }
>>>>> 
>>>>> And the analyzer cannot detect the warning anymore.
>>>>> 
>>>>> *****After studying a little bit in analyzer, I realize that I
>>>>> might
>>>>> need to add the IFN_ACCESS_WITH_SIZE as a known internal
>>>>> function
>>>>> into
>>>>> Analyzer, (similar as malloc), such as:
>>>>> 
>>>>> kfm.add ("malloc", std::make_unique<kf_malloc> ());
>>>>> 
>>>>> Is this correct understanding? 
>>>> 
>>>> Yes, though IFNs use a slightly different subclass and
>>>> registration
>>>> mechanism - see register_known_functions in analyzer/kf.cc, which
>>>> currently has:
>>>> 
>>>>   /* Internal fns the analyzer has known_functions for.  */
>>>>   {
>>>>     kfm.add (IFN_BUILTIN_EXPECT, std::make_unique<kf_expect> ());
>>>>   }
>>>> 
>>>> You'll want to add something similar for IFN_ACCESS_WITH_SIZE.
>>>> 
>>>>> I also need to define a “kf_access_with_size” class similar as
>>>>> “kf_malloc” and define the kf_access_with_size::impl_call_pre
>>>>> as
>>>>> well?
>>>> 
>>>> Yes.  Looks like you'll want to use:
>>>>   model->deref_value
>>>> to get at the region pointed to by the pointer, and 
>>>>   model->get_manager ()->get_sized_region () 
>>>> to get a region of the correct size for the access at that
>>>> address.
>>>> 
>>>> Normally we'd use model->get_store_value (region) to actually do
>>>> the
>>>> access and get the contents of memory, which should do the bounds
>>>> checking for you.  So the simplest approach is probably to do
>>>> that
>>>> and
>>>> discard the result, or perhaps for efficiency you could just call
>>>> check_region_for_read on it (but that might miss some special-
>>>> cases
>>>> e.g. when the region is zero-sized).
>>> 
>>> Or if this just a no-op pass through of the param 1, then the
>>> behavior
>>> of kf_expect might be appropriate.
>> 
>> IFN_ACCESS_WITH_SIZE should not be a no-op in analyzer.
>> From my understanding, it should be treated similar as a “malloc”,
>> and the size of the returned pointer 
>> Will be represented by 2nd (and 3rd) parameters. 
>> Qing
> 
> internal-fn.cc has:
> /* Expand the IFN_ACCESS_WITH_SIZE function:
>   ACCESS_WITH_SIZE (REF_TO_OBJ, REF_TO_SIZE,
>      TYPE_OF_SIZE + ACCESS_MODE, TYPE_SIZE_UNIT for element)
>   which returns the REF_TO_OBJ same as the 1st argument;
> 
>   [...snip...]
> 
>   For each call to a .ACCESS_WITH_SIZE, replace it with its 1st argument.  */
> 
> Isn't this more like IFN_BUILTIN_EXPECT than malloc?

The major purpose of IFN_ACCESS_WITH_SIZE is carrying the SIZE information for 
the returned pointer (which is same as the 1st argument). 

And the SIZE information carried by it could be used by the analyzer to report 
warnings or errors. 
So, when the analyzer see a call to malloc, how it get its SIZE information? 
(From the “alloc_size” attribute, I guess?  Because the call to 
.ACCESS_WITH_SIZE is 
generated to replace the attribute “alloc_size”).

Before my change, the IR is:

ptr = malloc (42);

After my change, the above IR become:

_1 = malloc (42);
ptr = .ACCESS_WITH_SIZE (_1, 42, 4B, 1);

How to integrate the IFN_ACCESS_WITH_SIZE call into the analyzer to provide the 
exactly same information as attribute “alloc_size”?

thanks.

Qing
>  I don't see where
> memory allocation would take place.  Are you wanting to have it capture
> knowledge about the size of the underlying memory region?  If so, then
> use region_model::set_dynamic_extents to let the bounds-checking code
> know about it.
> 
> Sorry if I'm missing something here
> Dave
> 
>>> 
>>> 
>>>> 
>>>> Dave
>>>> 
>>>>> 
>>>>> What else I need to do in analyzer to resolve this problem?
>>>>> 
>>>>> Thanks a lot for your help.
>>>>> 
>>>>> Qing


Reply via email to