Skip to content

Commit e060cd5

Browse files
committed
Avoid copying undefined data in _readA_Const().
nodeRead() will have created a Node struct that's only allocated big enough for the specific node type, so copying sizeof(union ValUnion) can be copying too much. This provokes valgrind complaints, and with very bad luck could perhaps result in SIGSEGV. While at it, tidy up _equalA_Const to avoid duplicate checks of isnull. Per report from Alexander Lakhin. This code is new as of a6bc330, so no need to back-patch. Discussion: https://postgr.es/m/4995256b-cc65-170e-0b22-60ad2cd535f1@gmail.com
1 parent 4f46f87 commit e060cd5

File tree

2 files changed

+27
-6
lines changed

2 files changed

+27
-6
lines changed

src/backend/nodes/equalfuncs.c

+3-5
Original file line numberDiff line numberDiff line change
@@ -133,13 +133,11 @@ _equalExtensibleNode(const ExtensibleNode *a, const ExtensibleNode *b)
133133
static bool
134134
_equalA_Const(const A_Const *a, const A_Const *b)
135135
{
136-
/*
137-
* Hack for in-line val field. Also val is not valid is isnull is true.
138-
*/
139-
if (!a->isnull && !b->isnull &&
136+
COMPARE_SCALAR_FIELD(isnull);
137+
/* Hack for in-line val field. Also val is not valid if isnull is true */
138+
if (!a->isnull &&
140139
!equal(&a->val, &b->val))
141140
return false;
142-
COMPARE_SCALAR_FIELD(isnull);
143141
COMPARE_LOCATION_FIELD(location);
144142

145143
return true;

src/backend/nodes/readfuncs.c

+24-1
Original file line numberDiff line numberDiff line change
@@ -305,14 +305,37 @@ _readA_Const(void)
305305
{
306306
READ_LOCALS(A_Const);
307307

308+
/* We expect either NULL or :val here */
308309
token = pg_strtok(&length);
309310
if (length == 4 && strncmp(token, "NULL", 4) == 0)
310311
local_node->isnull = true;
311312
else
312313
{
313314
union ValUnion *tmp = nodeRead(NULL, 0);
314315

315-
memcpy(&local_node->val, tmp, sizeof(*tmp));
316+
/* To forestall valgrind complaints, copy only the valid data */
317+
switch (nodeTag(tmp))
318+
{
319+
case T_Integer:
320+
memcpy(&local_node->val, tmp, sizeof(Integer));
321+
break;
322+
case T_Float:
323+
memcpy(&local_node->val, tmp, sizeof(Float));
324+
break;
325+
case T_Boolean:
326+
memcpy(&local_node->val, tmp, sizeof(Boolean));
327+
break;
328+
case T_String:
329+
memcpy(&local_node->val, tmp, sizeof(String));
330+
break;
331+
case T_BitString:
332+
memcpy(&local_node->val, tmp, sizeof(BitString));
333+
break;
334+
default:
335+
elog(ERROR, "unrecognized node type: %d",
336+
(int) nodeTag(tmp));
337+
break;
338+
}
316339
}
317340

318341
READ_LOCATION_FIELD(location);

0 commit comments

Comments
 (0)