Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitd660701

Browse files
Support json_errdetail in FRONTEND code
Allocate memory for the error message inside memory owned by theJsonLexContext and move responsibility away from the caller forfreeing it. This means that we can partially revertb44669bas this is now safe to use in FRONTEND code. The motivation forthis comes from the OAuth and incremental JSON patchsets but italso adds value on its own.Author: Jacob Champion <jacob.champion@enterprisedb.com>Reviewed-by: Michael Paquier <michael@paquier.xyz>Discussion:https://postgr.es/m/CAOYmi+mWdTd6ujtyF7MsvXvk7ToLRVG_tYAcaGbQLvf=N4KrQw@mail.gmail.com
1 parent33f1316 commitd660701

File tree

4 files changed

+73
-54
lines changed

4 files changed

+73
-54
lines changed

‎src/bin/pg_verifybackup/t/005_bad_manifest.pl

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@
1313
my$tempdir = PostgreSQL::Test::Utils::tempdir;
1414

1515
test_bad_manifest('input string ended unexpectedly',
16-
qr/could not parse backup manifest: parsing failed/,<<EOM);
16+
qr/could not parse backup manifest: The input string ended unexpectedly/,
17+
<<EOM);
1718
{
1819
EOM
1920

‎src/common/jsonapi.c

Lines changed: 69 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,7 @@ makeJsonLexContextCstringLen(JsonLexContext *lex, char *json,
161161
else
162162
memset(lex,0,sizeof(JsonLexContext));
163163

164+
lex->errormsg=NULL;
164165
lex->input=lex->token_terminator=lex->line_start=json;
165166
lex->line_number=1;
166167
lex->input_length=len;
@@ -175,18 +176,21 @@ makeJsonLexContextCstringLen(JsonLexContext *lex, char *json,
175176
}
176177

177178
/*
178-
* Free memory in a JsonLexContext. There's no need for this if a *lex
179-
* pointer was given when the object was made and need_escapes was false,
180-
* or (in backend environment) a memory context delete/reset is imminent.
179+
* Free memory in a JsonLexContext.
180+
*
181+
* There's no need for this if a *lex pointer was given when the object was
182+
* made, need_escapes was false, and json_errdetail() was not called; or if (in
183+
* backend environment) a memory context delete/reset is imminent.
181184
*/
182185
void
183186
freeJsonLexContext(JsonLexContext*lex)
184187
{
185188
if (lex->flags&JSONLEX_FREE_STRVAL)
186-
{
187-
pfree(lex->strval->data);
188-
pfree(lex->strval);
189-
}
189+
destroyStringInfo(lex->strval);
190+
191+
if (lex->errormsg)
192+
destroyStringInfo(lex->errormsg);
193+
190194
if (lex->flags&JSONLEX_FREE_STRUCT)
191195
pfree(lex);
192196
}
@@ -1145,72 +1149,71 @@ report_parse_error(JsonParseContext ctx, JsonLexContext *lex)
11451149
returnJSON_SUCCESS;/* silence stupider compilers */
11461150
}
11471151

1148-
1149-
#ifndefFRONTEND
1150-
/*
1151-
* Extract the current token from a lexing context, for error reporting.
1152-
*/
1153-
staticchar*
1154-
extract_token(JsonLexContext*lex)
1155-
{
1156-
inttoklen=lex->token_terminator-lex->token_start;
1157-
char*token=palloc(toklen+1);
1158-
1159-
memcpy(token,lex->token_start,toklen);
1160-
token[toklen]='\0';
1161-
returntoken;
1162-
}
1163-
11641152
/*
11651153
* Construct an (already translated) detail message for a JSON error.
11661154
*
1167-
* Note that the error message generated by this routine may not be
1168-
* palloc'd, making it unsafe for frontend code as there is no way to
1169-
* know if this can be safely pfree'd or not.
1155+
* The returned pointer should not be freed, the allocation is either static
1156+
* or owned by the JsonLexContext.
11701157
*/
11711158
char*
11721159
json_errdetail(JsonParseErrorTypeerror,JsonLexContext*lex)
11731160
{
1161+
if (lex->errormsg)
1162+
resetStringInfo(lex->errormsg);
1163+
else
1164+
lex->errormsg=makeStringInfo();
1165+
1166+
/*
1167+
* A helper for error messages that should print the current token. The
1168+
* format must contain exactly one %.*s specifier.
1169+
*/
1170+
#definetoken_error(lex,format) \
1171+
appendStringInfo((lex)->errormsg, _(format), \
1172+
(int) ((lex)->token_terminator - (lex)->token_start), \
1173+
(lex)->token_start);
1174+
11741175
switch (error)
11751176
{
11761177
caseJSON_SUCCESS:
11771178
/* fall through to the error code after switch */
11781179
break;
11791180
caseJSON_ESCAPING_INVALID:
1180-
returnpsprintf(_("Escape sequence \"\\%s\" is invalid."),
1181-
extract_token(lex));
1181+
token_error(lex,"Escape sequence \"\\%.*s\" is invalid.");
1182+
break;
11821183
caseJSON_ESCAPING_REQUIRED:
1183-
returnpsprintf(_("Character with value 0x%02x must be escaped."),
1184-
(unsignedchar)*(lex->token_terminator));
1184+
appendStringInfo(lex->errormsg,
1185+
_("Character with value 0x%02x must be escaped."),
1186+
(unsignedchar)*(lex->token_terminator));
1187+
break;
11851188
caseJSON_EXPECTED_END:
1186-
returnpsprintf(_("Expected end of input, but found \"%s\"."),
1187-
extract_token(lex));
1189+
token_error(lex,"Expected end of input, but found \"%.*s\".");
1190+
break;
11881191
caseJSON_EXPECTED_ARRAY_FIRST:
1189-
returnpsprintf(_("Expected array element or \"]\", but found \"%s\"."),
1190-
extract_token(lex));
1192+
token_error(lex,"Expected array element or \"]\", but found \"%.*s\".");
1193+
break;
11911194
caseJSON_EXPECTED_ARRAY_NEXT:
1192-
returnpsprintf(_("Expected \",\" or \"]\", but found \"%s\"."),
1193-
extract_token(lex));
1195+
token_error(lex,"Expected \",\" or \"]\", but found \"%.*s\".");
1196+
break;
11941197
caseJSON_EXPECTED_COLON:
1195-
returnpsprintf(_("Expected \":\", but found \"%s\"."),
1196-
extract_token(lex));
1198+
token_error(lex,"Expected \":\", but found \"%.*s\".");
1199+
break;
11971200
caseJSON_EXPECTED_JSON:
1198-
returnpsprintf(_("Expected JSON value, but found \"%s\"."),
1199-
extract_token(lex));
1201+
token_error(lex,"Expected JSON value, but found \"%.*s\".");
1202+
break;
12001203
caseJSON_EXPECTED_MORE:
12011204
return_("The input string ended unexpectedly.");
12021205
caseJSON_EXPECTED_OBJECT_FIRST:
1203-
returnpsprintf(_("Expected string or \"}\", but found \"%s\"."),
1204-
extract_token(lex));
1206+
token_error(lex,"Expected string or \"}\", but found \"%.*s\".");
1207+
break;
12051208
caseJSON_EXPECTED_OBJECT_NEXT:
1206-
returnpsprintf(_("Expected \",\" or \"}\", but found \"%s\"."),
1207-
extract_token(lex));
1209+
token_error(lex,"Expected \",\" or \"}\", but found \"%.*s\".");
1210+
break;
12081211
caseJSON_EXPECTED_STRING:
1209-
returnpsprintf(_("Expected string, but found \"%s\"."),
1210-
extract_token(lex));
1212+
token_error(lex,"Expected string, but found \"%.*s\".");
1213+
break;
12111214
caseJSON_INVALID_TOKEN:
1212-
returnpsprintf(_("Token \"%s\" is invalid."),
1213-
extract_token(lex));
1215+
token_error(lex,"Token \"%.*s\" is invalid.");
1216+
break;
12141217
caseJSON_UNICODE_CODE_POINT_ZERO:
12151218
return_("\\u0000 cannot be converted to text.");
12161219
caseJSON_UNICODE_ESCAPE_FORMAT:
@@ -1219,9 +1222,19 @@ json_errdetail(JsonParseErrorType error, JsonLexContext *lex)
12191222
/* note: this case is only reachable in frontend not backend */
12201223
return_("Unicode escape values cannot be used for code point values above 007F when the encoding is not UTF8.");
12211224
caseJSON_UNICODE_UNTRANSLATABLE:
1222-
/* note: this case is only reachable in backend not frontend */
1225+
1226+
/*
1227+
* Note: this case is only reachable in backend and not frontend.
1228+
* #ifdef it away so the frontend doesn't try to link against
1229+
* backend functionality.
1230+
*/
1231+
#ifndefFRONTEND
12231232
returnpsprintf(_("Unicode escape value could not be translated to the server's encoding %s."),
12241233
GetDatabaseEncodingName());
1234+
#else
1235+
Assert(false);
1236+
break;
1237+
#endif
12251238
caseJSON_UNICODE_HIGH_SURROGATE:
12261239
return_("Unicode high surrogate must not follow a high surrogate.");
12271240
caseJSON_UNICODE_LOW_SURROGATE:
@@ -1230,13 +1243,17 @@ json_errdetail(JsonParseErrorType error, JsonLexContext *lex)
12301243
/* fall through to the error code after switch */
12311244
break;
12321245
}
1246+
#undef token_error
12331247

12341248
/*
12351249
* We don't use a default: case, so that the compiler will warn about
12361250
* unhandled enum values. But this needs to be here anyway to cover the
12371251
* possibility of an incorrect input.
12381252
*/
1239-
elog(ERROR,"unexpected json parse error type: %d", (int)error);
1240-
returnNULL;
1253+
if (lex->errormsg->len==0)
1254+
appendStringInfo(lex->errormsg,
1255+
_("unexpected json parse error type: %d"),
1256+
(int)error);
1257+
1258+
returnlex->errormsg->data;
12411259
}
1242-
#endif

‎src/common/parse_manifest.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,7 @@ json_parse_manifest(JsonManifestParseContext *context, char *buffer,
152152
/* Run the actual JSON parser. */
153153
json_error=pg_parse_json(lex,&sem);
154154
if (json_error!=JSON_SUCCESS)
155-
json_manifest_parse_failure(context,"parsing failed");
155+
json_manifest_parse_failure(context,json_errdetail(json_error,lex));
156156
if (parse.state!=JM_EXPECT_EOF)
157157
json_manifest_parse_failure(context,"manifest ended unexpectedly");
158158

‎src/include/common/jsonapi.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ typedef struct JsonLexContext
8989
intline_number;/* line number, starting from 1 */
9090
char*line_start;/* where that line starts within input */
9191
StringInfostrval;
92+
StringInfoerrormsg;
9293
}JsonLexContext;
9394

9495
typedefJsonParseErrorType (*json_struct_action) (void*state);

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp