mirror of
https://git.savannah.gnu.org/git/make.git
synced 2024-12-24 12:58:39 +00:00
[SV 58497] Ensure $(file <) newline removal succeeds
Keep a count of bytes read rather than comparing pointers since the variable_buffer might get reallocated. Bug and patch by Ken Tossell <ken@tossell.net> Regression tests by Dmitry Goncharov <dgoncharov@users.sf.net> Tweaked by Paul Smith <psmith@gnu.org> * src/function.c (func_file): Use bytes read rather than a pointer. * tests/scripts/functions/file: Provide various tests for reading empty files, files with/without newlines, and large files.
This commit is contained in:
parent
510e5ce801
commit
c5319e75f5
3 changed files with 83 additions and 7 deletions
|
@ -2303,7 +2303,7 @@ func_file (char *o, char **argv, const char *funcname UNUSED)
|
|||
}
|
||||
else if (fn[0] == '<')
|
||||
{
|
||||
char *preo = o;
|
||||
size_t n = 0;
|
||||
FILE *fp;
|
||||
|
||||
++fn;
|
||||
|
@ -2327,8 +2327,10 @@ func_file (char *o, char **argv, const char *funcname UNUSED)
|
|||
char buf[1024];
|
||||
size_t l = fread (buf, 1, sizeof (buf), fp);
|
||||
if (l > 0)
|
||||
o = variable_buffer_output (o, buf, l);
|
||||
|
||||
{
|
||||
o = variable_buffer_output (o, buf, l);
|
||||
n += l;
|
||||
}
|
||||
if (ferror (fp))
|
||||
if (errno != EINTR)
|
||||
OSS (fatal, reading_file, _("read: %s: %s"), fn, strerror (errno));
|
||||
|
@ -2339,9 +2341,8 @@ func_file (char *o, char **argv, const char *funcname UNUSED)
|
|||
OSS (fatal, reading_file, _("close: %s: %s"), fn, strerror (errno));
|
||||
|
||||
/* Remove trailing newline. */
|
||||
if (o > preo && o[-1] == '\n')
|
||||
if (--o > preo && o[-1] == '\r')
|
||||
--o;
|
||||
if (n && o[-1] == '\n')
|
||||
o -= 1 + (n > 1 && o[-2] == '\r');
|
||||
}
|
||||
else
|
||||
OS (fatal, *expanding_var, _("file: invalid file operation: %s"), fn);
|
||||
|
|
|
@ -118,6 +118,76 @@ x:;@echo '$(X1)'; echo '$(A)'; echo '$(B)'
|
|||
|
||||
unlink('file.out');
|
||||
|
||||
# Read an empty file.
|
||||
touch("file.out");
|
||||
run_make_test(q!# empty file
|
||||
X1 := x$(file <file.out)y
|
||||
x:;@echo '$(X1)'
|
||||
!,
|
||||
'', "xy\n");
|
||||
|
||||
unlink('file.out');
|
||||
|
||||
# Read a file whose full contents is a newline.
|
||||
create_file('file.out', "\n");
|
||||
run_make_test(q!# <nl>
|
||||
X1 := x$(file <file.out)y
|
||||
x:;@echo '$(X1)'
|
||||
!,
|
||||
'', "xy\n");
|
||||
|
||||
unlink('file.out');
|
||||
|
||||
# Read a file which does not end with a newline.
|
||||
create_file('file.out', "hello");
|
||||
# echo prints a trailig newline, because run_make_test appends a newline.
|
||||
run_make_test(q!# hello
|
||||
X1 := x$(file <file.out)y
|
||||
x:;@echo $(X1)
|
||||
!,
|
||||
'', "xhelloy\n");
|
||||
|
||||
unlink('file.out');
|
||||
|
||||
# Read a file which ends with a newline.
|
||||
create_file('file.out', "hello\n");
|
||||
# echo prints a trailig newline, because run_make_test appends a newline.
|
||||
run_make_test(q!# hello<nl>
|
||||
X1 := x$(file <file.out)y
|
||||
x:;@echo '$(X1)'
|
||||
!,
|
||||
'', "xhelloy\n");
|
||||
|
||||
|
||||
unlink('file.out');
|
||||
|
||||
# Read a file which ends with multiple newlines.
|
||||
create_file('file.out', "hello\n\n");
|
||||
run_make_test(q!# hello<nl><nl>
|
||||
X1 := x$(file <file.out)y
|
||||
export X1
|
||||
x:;@echo "$$X1"
|
||||
!,
|
||||
'', "xhello\ny\n");
|
||||
|
||||
unlink('file.out');
|
||||
|
||||
# Read a file whose contents exceed 200 bytes.
|
||||
# 200 is the initial size of variable_buffer.
|
||||
# File bigger than 200 bytes causes a realloc.
|
||||
# The size of the file in this test not only exceeds 200 bytes, it exceeds 65k.
|
||||
|
||||
my $s = "hello world, hello world, hello world, hello world, hello world";
|
||||
my $answer = $s x 2000;
|
||||
create_file('file.out', $answer);
|
||||
run_make_test(q!# <hugestring>
|
||||
X1 := x$(file <file.out)y
|
||||
x:;@echo '$(X1)'
|
||||
!,
|
||||
'', "x${answer}y\n");
|
||||
|
||||
unlink('file.out');
|
||||
|
||||
# Reading from non-existent file
|
||||
run_make_test(q!
|
||||
X1 := $(file <file.out)
|
||||
|
|
|
@ -8,7 +8,8 @@
|
|||
# Each step consists of an operator and argument.
|
||||
#
|
||||
# It supports the following operators:
|
||||
# out <word> : echo <word> to stdout
|
||||
# out <word> : echo <word> to stdout with a newline
|
||||
# raw <word> : echo <word> to stdout without adding anything
|
||||
# file <word> : echo <word> to stdout AND create the file <word>
|
||||
# dir <word> : echo <word> to stdout AND create the directory <word>
|
||||
# rm <word> : echo <word> to stdout AND delete the file/directory <word>
|
||||
|
@ -34,6 +35,10 @@ sub op {
|
|||
print "$nm\n";
|
||||
return 1;
|
||||
}
|
||||
if ($op eq 'raw') {
|
||||
print "$nm";
|
||||
return 1;
|
||||
}
|
||||
|
||||
# Show the output before creating the file
|
||||
if ($op eq 'file') {
|
||||
|
|
Loading…
Reference in a new issue