Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 0736a8e

Browse files
committed
Use a safer outfuncs/readfuncs representation for BitStrings.
For a long time, our outfuncs.c code has supposed that the string contents of a BitString node could just be printed literally with no concern for quoting/escaping. Now, that's okay if the string literal contains only valid binary or hex digits ... but our lexer doesn't check that, preferring to let bitin() be the sole authority on what's valid. So we could have raw parse trees that contain incorrect BitString literals, and that can result in failures when WRITE_READ_PARSE_PLAN_TREES debugging is enabled. Fix by using outToken() to print the string field, and debackslash() to read it. This results in a change in the emitted representation only in cases that would have failed before, and don't represent valid SQL in the first place. Between that and the fact that we don't store raw parse trees in the catalogs, I judge this safe to apply without a catversion bump. Per bug #18340 from Alexander Lakhin. Back-patch to v16; before that, we lacked readfuncs support for BitString nodes, so that the problem was only cosmetic. Discussion: https://postgr.es/m/18340-4aa1ae6ed4121912@postgresql.org
1 parent c1fc502 commit 0736a8e

File tree

4 files changed

+32
-10
lines changed

4 files changed

+32
-10
lines changed

src/backend/nodes/outfuncs.c

+7-2
Original file line numberDiff line numberDiff line change
@@ -680,8 +680,13 @@ _outString(StringInfo str, const String *node)
680680
static void
681681
_outBitString(StringInfo str, const BitString *node)
682682
{
683-
/* internal representation already has leading 'b' */
684-
appendStringInfoString(str, node->bsval);
683+
/*
684+
* The lexer will always produce a string starting with 'b' or 'x'. There
685+
* might be characters following that that need escaping, but outToken
686+
* won't escape the 'b' or 'x'. This is relied on by nodeTokenType.
687+
*/
688+
Assert(node->bsval[0] == 'b' || node->bsval[0] == 'x');
689+
outToken(str, node->bsval);
685690
}
686691

687692
static void

src/backend/nodes/read.c

+3-8
Original file line numberDiff line numberDiff line change
@@ -498,14 +498,9 @@ nodeRead(const char *token, int tok_len)
498498
result = (Node *) makeString(debackslash(token + 1, tok_len - 2));
499499
break;
500500
case T_BitString:
501-
{
502-
char *val = palloc(tok_len + 1);
503-
504-
memcpy(val, token, tok_len);
505-
val[tok_len] = '\0';
506-
result = (Node *) makeBitString(val);
507-
break;
508-
}
501+
/* need to remove backslashes, but there are no quotes */
502+
result = (Node *) makeBitString(debackslash(token, tok_len));
503+
break;
509504
default:
510505
elog(ERROR, "unrecognized node type: %d", (int) type);
511506
result = NULL; /* keep compiler happy */

src/test/regress/expected/bit.out

+17
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,23 @@ SELECT * FROM VARBIT_TABLE;
4040
01010101010
4141
(4 rows)
4242

43+
-- Literals with syntax errors
44+
SELECT b' 0';
45+
ERROR: " " is not a valid binary digit
46+
LINE 1: SELECT b' 0';
47+
^
48+
SELECT b'0 ';
49+
ERROR: " " is not a valid binary digit
50+
LINE 1: SELECT b'0 ';
51+
^
52+
SELECT x' 0';
53+
ERROR: " " is not a valid hexadecimal digit
54+
LINE 1: SELECT x' 0';
55+
^
56+
SELECT x'0 ';
57+
ERROR: " " is not a valid hexadecimal digit
58+
LINE 1: SELECT x'0 ';
59+
^
4360
-- Concatenation
4461
SELECT v, b, (v || b) AS concat
4562
FROM BIT_TABLE, VARBIT_TABLE

src/test/regress/sql/bit.sql

+5
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,11 @@ INSERT INTO VARBIT_TABLE VALUES (B'101011111010'); -- too long
2929
--INSERT INTO VARBIT_TABLE VALUES ('X555');
3030
SELECT * FROM VARBIT_TABLE;
3131

32+
-- Literals with syntax errors
33+
SELECT b' 0';
34+
SELECT b'0 ';
35+
SELECT x' 0';
36+
SELECT x'0 ';
3237

3338
-- Concatenation
3439
SELECT v, b, (v || b) AS concat

0 commit comments

Comments
 (0)