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

Commite8476f4

Browse files
committed
Fix COPY FROM for null marker strings that correspond to invalid encoding.
The COPY documentation says "COPY FROM matches the input against the nullstring before removing backslashes". It is therefore reasonable to presumethat null markers like E'\\0' will work ... and they did, until someone putthe tests in the wrong order during microoptimization-driven rewrites.Since then, we've been failing if the null marker is something that wouldde-escape to an invalidly-encoded string. Since null markers generallyneed to be something that can't appear in the data, this represents anontrivial loss of functionality; surprising nobody noticed it earlier.Per report from Jeff Davis. Backpatch to 8.4 where this got broken.
1 parentc7cea26 commite8476f4

File tree

3 files changed

+60
-16
lines changed

3 files changed

+60
-16
lines changed

‎src/backend/commands/copy.c

Lines changed: 29 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -3243,7 +3243,17 @@ CopyReadAttributesText(CopyState cstate)
32433243
start_ptr=cur_ptr;
32443244
cstate->raw_fields[fieldno]=output_ptr;
32453245

3246-
/* Scan data for field */
3246+
/*
3247+
* Scan data for field.
3248+
*
3249+
* Note that in this loop, we are scanning to locate the end of field
3250+
* and also speculatively performing de-escaping. Once we find the
3251+
* end-of-field, we can match the raw field contents against the null
3252+
* marker string. Only after that comparison fails do we know that
3253+
* de-escaping is actually the right thing to do; therefore we *must
3254+
* not* throw any syntax errors before we've done the null-marker
3255+
* check.
3256+
*/
32473257
for (;;)
32483258
{
32493259
charc;
@@ -3356,26 +3366,29 @@ CopyReadAttributesText(CopyState cstate)
33563366
*output_ptr++=c;
33573367
}
33583368

3359-
/* Terminate attribute value in output area */
3360-
*output_ptr++='\0';
3361-
3362-
/*
3363-
* If we de-escaped a non-7-bit-ASCII char, make sure we still have
3364-
* valid data for the db encoding. Avoid calling strlen here for the
3365-
* sake of efficiency.
3366-
*/
3367-
if (saw_non_ascii)
3368-
{
3369-
char*fld=cstate->raw_fields[fieldno];
3370-
3371-
pg_verifymbstr(fld,output_ptr- (fld+1), false);
3372-
}
3373-
33743369
/* Check whether raw input matched null marker */
33753370
input_len=end_ptr-start_ptr;
33763371
if (input_len==cstate->null_print_len&&
33773372
strncmp(start_ptr,cstate->null_print,input_len)==0)
33783373
cstate->raw_fields[fieldno]=NULL;
3374+
else
3375+
{
3376+
/*
3377+
* At this point we know the field is supposed to contain data.
3378+
*
3379+
* If we de-escaped any non-7-bit-ASCII chars, make sure the
3380+
* resulting string is valid data for the db encoding.
3381+
*/
3382+
if (saw_non_ascii)
3383+
{
3384+
char*fld=cstate->raw_fields[fieldno];
3385+
3386+
pg_verifymbstr(fld,output_ptr-fld, false);
3387+
}
3388+
}
3389+
3390+
/* Terminate attribute value in output area */
3391+
*output_ptr++='\0';
33793392

33803393
fieldno++;
33813394
/* Done if we hit EOL instead of a delim */

‎src/test/regress/expected/copy2.out

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,22 @@ a\.
239239
\.b
240240
c\.d
241241
"\."
242+
-- test handling of nonstandard null marker that violates escaping rules
243+
CREATE TEMP TABLE testnull(a int, b text);
244+
INSERT INTO testnull VALUES (1, E'\\0'), (NULL, NULL);
245+
COPY testnull TO stdout WITH NULL AS E'\\0';
246+
1\\0
247+
\0\0
248+
COPY testnull FROM stdin WITH NULL AS E'\\0';
249+
SELECT * FROM testnull;
250+
a | b
251+
----+----
252+
1 | \0
253+
|
254+
42 | \0
255+
|
256+
(4 rows)
257+
242258
DROP TABLE x, y;
243259
DROP FUNCTION fn_x_before();
244260
DROP FUNCTION fn_x_after();

‎src/test/regress/sql/copy2.sql

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,21 @@ c\.d
164164

165165
COPY testeoc TO stdout CSV;
166166

167+
-- test handling of nonstandard null marker that violates escaping rules
168+
169+
CREATE TEMP TABLE testnull(aint, btext);
170+
INSERT INTO testnullVALUES (1, E'\\0'), (NULL,NULL);
171+
172+
COPY testnull TO stdout WITHNULLAS E'\\0';
173+
174+
COPY testnullFROM stdin WITHNULLAS E'\\0';
175+
42\\0
176+
\0\0
177+
\.
178+
179+
SELECT*FROM testnull;
180+
181+
167182
DROPTABLE x, y;
168183
DROPFUNCTION fn_x_before();
169184
DROPFUNCTION fn_x_after();

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp