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

Commit 6cfb3a3

Browse files
committed
Strip Windows newlines from extension script files manually.
Revert commit 924e039 in favor of adding code to convert \r\n to \n explicitly, on Windows only. The idea of letting text mode do the work fails for a couple of reasons: * Per Microsoft documentation, text mode also causes control-Z to be interpreted as end-of-file. While it may be unlikely that extension scripts contain control-Z, we've historically allowed it, and breaking the case doesn't seem wise. * Apparently, on some Windows configurations, "r" mode is interpreted as binary not text mode. We could force it with "rt" but that would be inconsistent with our code elsewhere, and it would still require Windows-specific coding. Thanks to Alexander Lakhin for investigation. Discussion: https://postgr.es/m/79284195-4993-7b00-f6df-8db28ca60fa3@gmail.com
1 parent 8a98822 commit 6cfb3a3

File tree

1 file changed

+34
-4
lines changed

1 file changed

+34
-4
lines changed

src/backend/commands/extension.c

Lines changed: 34 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -724,6 +724,10 @@ script_error_callback(void *arg)
724724
* certainly possible to fool this with semicolon-newline embedded
725725
* in a string literal, but it seems better to do this than to
726726
* show the entire extension script.
727+
*
728+
* Notice we cope with Windows-style newlines (\r\n) regardless of
729+
* platform. This is because there might be such newlines in
730+
* script files on other platforms.
727731
*/
728732
int slen = strlen(query);
729733

@@ -3618,7 +3622,8 @@ ExecAlterExtensionContentsRecurse(AlterExtensionContentsStmt *stmt,
36183622
* Read the whole of file into memory.
36193623
*
36203624
* The file contents are returned as a single palloc'd chunk. For convenience
3621-
* of the callers, an extra \0 byte is added to the end.
3625+
* of the callers, an extra \0 byte is added to the end. That is not counted
3626+
* in the length returned into *length.
36223627
*/
36233628
static char *
36243629
read_whole_file(const char *filename, int *length)
@@ -3639,15 +3644,15 @@ read_whole_file(const char *filename, int *length)
36393644
errmsg("file \"%s\" is too large", filename)));
36403645
bytes_to_read = (size_t) fst.st_size;
36413646

3642-
if ((file = AllocateFile(filename, "r")) == NULL)
3647+
if ((file = AllocateFile(filename, PG_BINARY_R)) == NULL)
36433648
ereport(ERROR,
36443649
(errcode_for_file_access(),
36453650
errmsg("could not open file \"%s\" for reading: %m",
36463651
filename)));
36473652

36483653
buf = (char *) palloc(bytes_to_read + 1);
36493654

3650-
*length = fread(buf, 1, bytes_to_read, file);
3655+
bytes_to_read = fread(buf, 1, bytes_to_read, file);
36513656

36523657
if (ferror(file))
36533658
ereport(ERROR,
@@ -3656,6 +3661,31 @@ read_whole_file(const char *filename, int *length)
36563661

36573662
FreeFile(file);
36583663

3659-
buf[*length] = '\0';
3664+
buf[bytes_to_read] = '\0';
3665+
3666+
/*
3667+
* On Windows, manually convert Windows-style newlines (\r\n) to the Unix
3668+
* convention of \n only. This avoids gotchas due to script files
3669+
* possibly getting converted when being transferred between platforms.
3670+
* Ideally we'd do this by using text mode to read the file, but that also
3671+
* causes control-Z to be treated as end-of-file. Historically we've
3672+
* allowed control-Z in script files, so breaking that seems unwise.
3673+
*/
3674+
#ifdef WIN32
3675+
{
3676+
char *s,
3677+
*d;
3678+
3679+
for (s = d = buf; *s; s++)
3680+
{
3681+
if (!(*s == '\r' && s[1] == '\n'))
3682+
*d++ = *s;
3683+
}
3684+
*d = '\0';
3685+
bytes_to_read = d - buf;
3686+
}
3687+
#endif
3688+
3689+
*length = bytes_to_read;
36603690
return buf;
36613691
}

0 commit comments

Comments
 (0)