From b4b2fcd5ea3f7e5631b49078e3ee1feb771e9c52 Mon Sep 17 00:00:00 2001 From: Shveta Malik Date: Tue, 1 Sep 2026 15:56:04 +0530 Subject: [PATCH] json-numeric fix --- src/backend/utils/adt/json.c | 66 +++++++++++++++++++++++++----------- 1 file changed, 47 insertions(+), 19 deletions(-) diff --git a/src/backend/utils/adt/json.c b/src/backend/utils/adt/json.c index aa41665a2e6..1517ebb6511 100644 --- a/src/backend/utils/adt/json.c +++ b/src/backend/utils/adt/json.c @@ -296,27 +296,55 @@ datum_to_json_internal(Datum val, bool is_null, StringInfo result, appendStringInfoChar(result, '"'); break; case JSONTYPE_NUMERIC: - outputstr = OidOutputFunctionCall(outfuncoid, val); - - /* - * Don't quote a non-key if it's a valid JSON number (i.e., not - * "Infinity", "-Infinity", or "NaN"). Since we know this is a - * numeric data type's output, we simplify and open-code the - * validation for better performance. - */ - if (!key_scalar && - ((*outputstr >= '0' && *outputstr <= '9') || - (*outputstr == '-' && - (outputstr[1] >= '0' && outputstr[1] <= '9')))) - appendStringInfoString(result, outputstr); - else { - appendStringInfoChar(result, '"'); - appendStringInfoString(result, outputstr); - appendStringInfoChar(result, '"'); + Size saved_limit = json_size_limit; + bool saved_hit = json_size_limit_hit; + + /* + * Suspend the size limit before invoking type output or cast + * functions. This prevents intermediate internal operations + * from prematurely triggering the limit, while the final + * returned output is still strictly measured against the + * threshold immediately after. + */ + json_set_size_limit(0); + + /* + * JSON and JSONB output are already escaped, so we can call + * their output functions directly without extra escaping. + * Check the rendered length before appending to result. + */ + outputstr = OidOutputFunctionCall(outfuncoid, val); + + json_size_limit = saved_limit; + json_size_limit_hit = saved_hit; + + if (json_size_would_exceed(result->len, strlen(outputstr))) + { + pfree(outputstr); + return; + } + + /* + * Don't quote a non-key if it's a valid JSON number (i.e., + * not "Infinity", "-Infinity", or "NaN"). Since we know this + * is a numeric data type's output, we simplify and open-code + * the validation for better performance. + */ + if (!key_scalar && + ((*outputstr >= '0' && *outputstr <= '9') || + (*outputstr == '-' && + (outputstr[1] >= '0' && outputstr[1] <= '9')))) + appendStringInfoString(result, outputstr); + else + { + appendStringInfoChar(result, '"'); + appendStringInfoString(result, outputstr); + appendStringInfoChar(result, '"'); + } + pfree(outputstr); + break; } - pfree(outputstr); - break; case JSONTYPE_DATE: { char buf[MAXDATELEN + 1]; -- 2.34.1