Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions src/backend/utils/adt/agtype.c
Original file line number Diff line number Diff line change
Expand Up @@ -6556,7 +6556,7 @@ Datum age_tofloatlist(PG_FUNCTION_ARGS)
int i;
bool is_valid = false;
float8 float_num;
char buffer[64];
char buffer[400];
Copy link

Copilot AI Apr 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

char buffer[400]; is a new magic number on the stack. Since the required size is derived from DBL_MAX_10_EXP and the chosen formatting/precision, consider defining a named constant (or computing the bound) so it's clear why 400 is sufficient and future format changes don't accidentally reintroduce truncation/overflow risks.

Copilot uses AI. Check for mistakes.

/* check for null */
if (PG_ARGISNULL(0))
Expand Down Expand Up @@ -6618,7 +6618,7 @@ Datum age_tofloatlist(PG_FUNCTION_ARGS)

float_elem.type = AGTV_FLOAT;
float_num = elem->val.float_value;
sprintf(buffer, "%f", float_num);
snprintf(buffer, sizeof(buffer), "%f", float_num);
string = buffer;
Comment on lines +6621 to 6622
Copy link

Copilot AI Apr 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change fixes a security-sensitive crash vector (very large float formatted via %f). There are existing regression tests for toFloatList() in regress/sql/expr.sql, but none appear to cover extremely large float values (e.g., something near DBL_MAX). Adding a regression case that exercises toFloatList([<very large float>]) would help prevent reintroducing the overflow/truncation issue.

Copilot uses AI. Check for mistakes.
float_elem.val.float_value = float8in_internal_null(string, NULL, "double precision", string, &is_valid);
Comment on lines 6620 to 6623
Copy link

Copilot AI Apr 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The PR description mentions increasing the buffer to "allow full precision", but this code still formats with "%f" (default precision 6), which both loses precision and expands large values (e.g., DBL_MAX) into hundreds of digits. Consider avoiding fixed-point formatting here by using Postgres' float8out output (or a "%.*g" with DBL_DECIMAL_DIG) so the conversion is round-trippable without requiring such a large stack buffer.

Copilot uses AI. Check for mistakes.
agis_result.res = push_agtype_value(&agis_result.parse_state, WAGT_ELEM, &float_elem);
Expand Down Expand Up @@ -7574,7 +7574,7 @@ Datum age_tostringlist(PG_FUNCTION_ARGS)

case AGTV_FLOAT:

sprintf(buffer, "%.*g", DBL_DIG, elem->val.float_value);
snprintf(buffer, sizeof(buffer), "%.*g", DBL_DIG, elem->val.float_value);
string_elem.val.string.val = pstrdup(buffer);
string_elem.val.string.len = strlen(buffer);

Expand All @@ -7585,7 +7585,7 @@ Datum age_tostringlist(PG_FUNCTION_ARGS)

case AGTV_INTEGER:

sprintf(buffer, "%ld", elem->val.int_value);
snprintf(buffer, sizeof(buffer), "%ld", elem->val.int_value);
Copy link

Copilot AI Apr 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

elem->val.int_value is an int64 (see struct agtype_value), but the format string uses %ld, which is not portable (e.g., long is 32-bit on some platforms) and can lead to incorrect output/UB. Use INT64_FORMAT (or pg_lltoa / int8out) when formatting int64 values.

Suggested change
snprintf(buffer, sizeof(buffer), "%ld", elem->val.int_value);
snprintf(buffer, sizeof(buffer), INT64_FORMAT, elem->val.int_value);

Copilot uses AI. Check for mistakes.
string_elem.val.string.val = pstrdup(buffer);
string_elem.val.string.len = strlen(buffer);

Expand Down
Loading