Skip to content

Commit b44669b

Browse files
committed
Simplify error handing of jsonapi.c for the frontend
This commit removes a dependency to the central logging facilities in the JSON parsing routines of src/common/, which existed to log errors when seeing error codes that do not match any existing values in JsonParseErrorType, which is not something that should never happen. The routine providing a detailed error message based on the error code is made backend-only, the existing code being unsafe to use in the frontend as the error message may finish by being palloc'd or point to a static string, so there is no way to know if the memory of the message should be pfree'd or not. The only user of this routine in the frontend was pg_verifybackup, that is changed to use a more generic error message on parsing failure. Note that making this code more resilient to OOM failures if used in shared libraries would require much more work as a lot of code paths still rely on palloc() & friends, but we are not sure yet if we need to go down to that. Still, removing the dependency to logging is a step toward more portability. This cleans up the handling of check_stack_depth() while on it, as it exists only in the backend. Per discussion with Jacob Champion and Tom Lane. Discussion: https://postgr.es/m/YNwL7kXwn3Cckbd6@paquier.xyz
1 parent 1708f6b commit b44669b

File tree

3 files changed

+32
-33
lines changed

3 files changed

+32
-33
lines changed

src/bin/pg_verifybackup/parse_manifest.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,7 @@ json_parse_manifest(JsonManifestParseContext *context, char *buffer,
147147
/* Run the actual JSON parser. */
148148
json_error = pg_parse_json(lex, &sem);
149149
if (json_error != JSON_SUCCESS)
150-
json_manifest_parse_failure(context, json_errdetail(json_error, lex));
150+
json_manifest_parse_failure(context, "parsing failed");
151151
if (parse.state != JM_EXPECT_EOF)
152152
json_manifest_parse_failure(context, "manifest ended unexpectedly");
153153

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616

1717
test_bad_manifest(
1818
'input string ended unexpectedly',
19-
qr/could not parse backup manifest: The input string ended unexpectedly/,
19+
qr/could not parse backup manifest: parsing failed/,
2020
<<EOM);
2121
{
2222
EOM

src/common/jsonapi.c

+30-31
Original file line numberDiff line numberDiff line change
@@ -20,20 +20,10 @@
2020
#include "common/jsonapi.h"
2121
#include "mb/pg_wchar.h"
2222

23-
#ifdef FRONTEND
24-
#include "common/logging.h"
25-
#else
23+
#ifndef FRONTEND
2624
#include "miscadmin.h"
2725
#endif
2826

29-
#ifdef FRONTEND
30-
#define check_stack_depth()
31-
#define json_log_and_abort(...) \
32-
do { pg_log_fatal(__VA_ARGS__); exit(1); } while(0)
33-
#else
34-
#define json_log_and_abort(...) elog(ERROR, __VA_ARGS__)
35-
#endif
36-
3727
/*
3828
* The context of the parser is maintained by the recursive descent
3929
* mechanism, but is passed explicitly to the error reporting routine
@@ -61,7 +51,6 @@ static JsonParseErrorType parse_object(JsonLexContext *lex, JsonSemAction *sem);
6151
static JsonParseErrorType parse_array_element(JsonLexContext *lex, JsonSemAction *sem);
6252
static JsonParseErrorType parse_array(JsonLexContext *lex, JsonSemAction *sem);
6353
static JsonParseErrorType report_parse_error(JsonParseContext ctx, JsonLexContext *lex);
64-
static char *extract_token(JsonLexContext *lex);
6554

6655
/* the null action object used for pure validation */
6756
JsonSemAction nullSemAction =
@@ -378,7 +367,9 @@ parse_object(JsonLexContext *lex, JsonSemAction *sem)
378367
JsonTokenType tok;
379368
JsonParseErrorType result;
380369

370+
#ifndef FRONTEND
381371
check_stack_depth();
372+
#endif
382373

383374
if (ostart != NULL)
384375
(*ostart) (sem->semstate);
@@ -478,7 +469,9 @@ parse_array(JsonLexContext *lex, JsonSemAction *sem)
478469
json_struct_action aend = sem->array_end;
479470
JsonParseErrorType result;
480471

472+
#ifndef FRONTEND
481473
check_stack_depth();
474+
#endif
482475

483476
if (astart != NULL)
484477
(*astart) (sem->semstate);
@@ -1044,15 +1037,34 @@ report_parse_error(JsonParseContext ctx, JsonLexContext *lex)
10441037

10451038
/*
10461039
* We don't use a default: case, so that the compiler will warn about
1047-
* unhandled enum values. But this needs to be here anyway to cover the
1048-
* possibility of an incorrect input.
1040+
* unhandled enum values.
10491041
*/
1050-
json_log_and_abort("unexpected json parse state: %d", (int) ctx);
1042+
Assert(false);
10511043
return JSON_SUCCESS; /* silence stupider compilers */
10521044
}
10531045

1046+
1047+
#ifndef FRONTEND
1048+
/*
1049+
* Extract the current token from a lexing context, for error reporting.
1050+
*/
1051+
static char *
1052+
extract_token(JsonLexContext *lex)
1053+
{
1054+
int toklen = lex->token_terminator - lex->token_start;
1055+
char *token = palloc(toklen + 1);
1056+
1057+
memcpy(token, lex->token_start, toklen);
1058+
token[toklen] = '\0';
1059+
return token;
1060+
}
1061+
10541062
/*
10551063
* Construct a detail message for a JSON error.
1064+
*
1065+
* Note that the error message generated by this routine may not be
1066+
* palloc'd, making it unsafe for frontend code as there is no way to
1067+
* know if this can be safery pfree'd or not.
10561068
*/
10571069
char *
10581070
json_errdetail(JsonParseErrorType error, JsonLexContext *lex)
@@ -1115,20 +1127,7 @@ json_errdetail(JsonParseErrorType error, JsonLexContext *lex)
11151127
* unhandled enum values. But this needs to be here anyway to cover the
11161128
* possibility of an incorrect input.
11171129
*/
1118-
json_log_and_abort("unexpected json parse error type: %d", (int) error);
1119-
return NULL; /* silence stupider compilers */
1120-
}
1121-
1122-
/*
1123-
* Extract the current token from a lexing context, for error reporting.
1124-
*/
1125-
static char *
1126-
extract_token(JsonLexContext *lex)
1127-
{
1128-
int toklen = lex->token_terminator - lex->token_start;
1129-
char *token = palloc(toklen + 1);
1130-
1131-
memcpy(token, lex->token_start, toklen);
1132-
token[toklen] = '\0';
1133-
return token;
1130+
elog(ERROR, "unexpected json parse error type: %d", (int) error);
1131+
return NULL;
11341132
}
1133+
#endif

0 commit comments

Comments
 (0)