From b4b2fcd5ea3f7e5631b49078e3ee1feb771e9c52 Mon Sep 17 00:00:00 2001
From: Shveta Malik <shveta.malik@gmail.com>
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

