summaryrefslogtreecommitdiff
path: root/src/function.c
diff options
context:
space:
mode:
authorPaul Smith <psmith@gnu.org>2021-03-15 03:28:11 -0400
committerPaul Smith <psmith@gnu.org>2021-03-15 03:28:11 -0400
commitc5319e75f5b64c972a38967a6eb5747838e914fd (patch)
treef15966e1da0e6d0e05e35358c198dfe99bad5b8c /src/function.c
parent510e5ce801d957338be764a794f1463b662a7edc (diff)
downloadmake-git-c5319e75f5b64c972a38967a6eb5747838e914fd.tar.gz
[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.
Diffstat (limited to 'src/function.c')
-rw-r--r--src/function.c13
1 files changed, 7 insertions, 6 deletions
diff --git a/src/function.c b/src/function.c
index d36b7951..396f1297 100644
--- a/src/function.c
+++ b/src/function.c
@@ -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);