Обсуждение: BUG #18908: DEREF_OF_NULL: After having been assigned to a NULL value at descriptor.c:203
BUG #18908: DEREF_OF_NULL: After having been assigned to a NULL value at descriptor.c:203
The following bug has been logged on the website: Bug reference: 18908 Logged by: Eugeny Goryachev Email address: gorcom2012@gmail.com PostgreSQL version: 17.4 Operating system: Ubuntu Description: DEREF_OF_NULL.EX.COND After having been assigned to a NULL value at descriptor.c:203, pointer '0' is passed as 5th parameter in call to function 'ECPGdump_a_type' at descriptor.c:203, where it is dereferenced at type.c:332. In the file /src/interfaces/ecpg/preproc/descriptor.c, in the function output_get_descr(), there is a call to ECPGdump_a_type() with an explicit NULL passed as the 5th parameter: void output_get_descr(char *desc_name, char *index) { *** ECPGdump_a_type(base_yyout, v->name, v->type, v->brace_level, NULL, NULL, -1, NULL, NULL, str_zero, NULL, NULL); *** } This NULL parameter is then passed to the ECPGdump_a_struct() function, where it gets dereferenced: static void ECPGdump_a_struct(FILE *o, const char *name, const char *ind_name, char *arrsize, struct ECPGtype *type, struct ECPGtype *ind_type, const char *prefix, const char *ind_prefix) { *** char *pbuf = (char *) mm_alloc(strlen(name) + ((prefix == NULL) ? 0 : strlen(prefix)) + 3); *** } When name == NULL, the strlen(name) call will cause a Segmentation Fault. To fix this issue, I propose the following patch: diff --git a/src/interfaces/ecpg/preproc/type.c b/src/interfaces/ecpg/preproc/type.c index a842bb6a1fe..7ffae74bcf2 100644 --- a/src/interfaces/ecpg/preproc/type.c +++ b/src/interfaces/ecpg/preproc/type.c @@ -587,7 +587,7 @@ ECPGdump_a_struct(FILE *o, const char *name, const char *ind_name, char *arrsize struct ECPGstruct_member *p, *ind_p = NULL; char *pbuf = (char *) mm_alloc(strlen(name) + ((prefix == NULL) ? 0 : strlen(prefix)) + 3); - char *ind_pbuf = (char *) mm_alloc(strlen(ind_name) + ((ind_prefix == NULL) ? 0 : strlen(ind_prefix)) + 3); + char *ind_pbuf = (char *) mm_alloc(((ind_name == NULL) ? 0 : strlen(ind_name)) + ((ind_prefix == NULL) ? 0 : strlen(ind_prefix)) + 3); if (atoi(arrsize) == 1) sprintf(pbuf, "%s%s.", prefix ? prefix : "", name);
Re: BUG #18908: DEREF_OF_NULL: After having been assigned to a NULL value at descriptor.c:203
Hello Eugeny! On Wed Apr 30, 2025 at 14:25:56 GMT +03, PG Bug reporting form wrote: > DEREF_OF_NULL.EX.COND After having been assigned to a NULL value at > descriptor.c:203, pointer '0' is passed as 5th parameter in call to function > 'ECPGdump_a_type' at descriptor.c:203, where it is dereferenced at > type.c:332. Perhaps you can provide a pgc file that triggers the bug? Best regards, Robin -- Robin Haberkorn Senior Software Engineer B1 Systems GmbH Osterfeldstraße 7 / 85088 Vohburg / https://www.b1-systems.de GF: Ralph Dehner / Unternehmenssitz: Vohburg / AG: Ingolstadt, HRB 3537
Re: BUG #18908: DEREF_OF_NULL: After having been assigned to a NULL value at descriptor.c:203
Hello,
This is regarding bug report BUG #18908: 18908-6531c66d23729837@postgresql.org.
I have reviewed this block of code and concluded that it does not require any fixes. This is a false positive from the static analyzer.
In the output_get_descr()
function, there is a call:
```
ECPGdump_a_type(base_yyout, v->name, v->type, v->brace_level,
NULL, NULL, -1, NULL, NULL, str_zero, NULL, NULL);
```where the 5th parameter is passed as
NULL
.Then, in the
ECPGdump_a_type()
function, this 5th parameter is defined asind_name
and is passed as the 3rd parameter to:
```
ECPGdump_a_struct(o, name, ind_name, str_one, type, ind_type, prefix, ind_prefix);
```
InECPGdump_a_struct()
, there is a dereference of theind_name
pointer:
```
char *ind_pbuf = (char *) mm_alloc(strlen(ind_name) + ((ind_prefix == NULL) ? 0 : strlen(ind_prefix)) + 3);
```Here, if
ind_name == NULL
, callingstrlen(ind_name)
would cause a process crash (segmentation fault).To demonstrate that this can never happen and that the analyzer is mistaken, let’s look at the condition under which
ECPGdump_a_struct()
is called fromECPGdump_a_type()
:
```
switch (type->type)
{
case ECPGt_struct:
```That is, only if the processed variable is of type struct.
However,
output_get_descr()
never processes structs — it only works with descriptors.The field
type->type
(which isv->type
) comes from:
```
const struct variable *v = find_variable(results->variable);
```But in
output_get_descr()
, we process descriptor fields (SQLDA), andresults->value
is one of the descriptor’s fields.All these fields are primitive types, not structs:
```
/* descriptor items */
enum ECPGdtype
{
ECPGd_count = 1,
ECPGd_data,
ECPGd_di_code,
ECPGd_di_precision,
ECPGd_indicator,
ECPGd_key_member,
ECPGd_length,
ECPGd_name,
ECPGd_nullable,
ECPGd_octet,
ECPGd_precision,
ECPGd_ret_length,
ECPGd_ret_octet,
ECPGd_scale,
ECPGd_type,
ECPGd_EODT, /* End of descriptor types. */
ECPGd_cardinality
};
```Therefore,
ECPGdump_a_struct()
will never be called fromoutput_get_descr()
because:
v->type->type
will never beECPGt_struct
in this context;
results->value
refers to descriptor fields, not C structs.Consequently, a call to
strlen(ind_name)
withind_name == NULL
is unreachable.Best regards, Eugeny Goryachev