Обсуждение: Fix mismatched deallocation functions

Поиск
Список
Период
Сортировка

Fix mismatched deallocation functions

От
"Tristan Partin"
Дата:
In fe_memutils.h, we have two sets of allocation/deallocation functions:
those that start pg_ and those that start with p. pg_malloc vs palloc,
pg_free vs pfree, etc. My understanding is that we probably want to
match the allocator with the deallocator whenever possible, but that is
not the case in HEAD. We have quite a few mismatches.

I discovered these issues when adding some __attribute__((malloc))
annotations to our allocation functions. gcc presents warnings in the
form of:

    ../src/bin/psql/tab-complete.in.c: In function ‘psql_completion’:
    ../src/bin/psql/tab-complete.in.c:2143:9: warning: ‘free’ called on pointer returned from a mismatched allocation
function[-Wmismatched-dealloc] 
     2143 |         free(text_copy);
          |         ^~~~~~~~~~~~~~~
    ../src/bin/psql/tab-complete.in.c:1971:33: note: returned from ‘pnstrdup’
     1971 |         char       *text_copy = pnstrdup(rl_line_buffer + start, end - start);
          |                                 ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Memory that we allocated pnstrdup() is being deallocated with free().
In actuality, this is not an issue because pnstrdup() uses malloc()
internally. However, it does create a little bit of mental overhead when
analyzing memory management in code paths. Warnings like this are also
a barrier to annotating our memory allocation functions with
__attribute__((malloc)).

The supplied patch allows for a clean compliation on my Linux x86_64
machine with malloc attribute applied. I will send that patch later
after a little bit more development.

I generated the patch with the help of Coccinelle[0]. I'm no expert with
Coccinelle, but it seemed like a good candidate to get this refactor
done. You can run the attached script in your tree with the following
command:

    spatch --sp-file allocators.cocci --allow-inconsistent-paths \
        --in-place .

[0]: https://coccinelle.gitlabpages.inria.fr/website/

--
Tristan Partin
PostgreSQL Contributors Team
AWS (https://aws.amazon.com)

Вложения

Re: Fix mismatched deallocation functions

От
Zsolt Parragi
Дата:
Hello!

There are many cases missed by the script, for example:

tab-complete.in.c:7089:

`previous_words = pg_malloc_array(char *, point);`

tab-complete.in.c:6364:

`completion_ref_object = pg_strdup(word);`

tab-complete.in.c:7090:

`*buffer = (char *) pg_malloc(point * 2);`

There's also completion_ref_schema, which is an out parameter of
parse_identifier, still freed in the patch.

The strtokx change in stringutils.c is also strange - the patch
converts one free at line 96, and leaves the same free a few lines
above at line 73 as is.

> I generated the patch with the help of Coccinelle[0]. I'm no expert with
> Coccinelle, but it seemed like a good candidate to get this refactor
> done. You can run the attached script in your tree with the following
> command:

If I had to do it, I would try to approach this with static analysis
tools instead: a custom rule that enforces attribute declarations for
return values / output parameters allocated by pg_malloc and similar
functions. Without attributes everywhere, these checks will never be
complete because tools won't be able to fully reason about cross
source file call paths.
For example clang-tidy even has an auto fix mode that could apply
these attributes automatically.

With the attributes in place, we would automatically receive warnings
for every incorrect free attribute, which a tool could then
automatically fix.

If we want to avoid generating noise by placing attributes everywhere
in the source (I'm not sure how noisy that would be), that part could
be a specialized CI run instead, since the transformation itself can
be automated.