commit: ffa5bb3da37734168c867ac5780b34fe099abff7
parent 3f2a057b9e72347217ad1bda14695daef6ca1c33
Author: Haelwenn (lanodan) Monnier <contact@hacktivis.me>
Date: Thu, 15 Aug 2024 19:53:43 +0200
cmd/sha1sum: replace scanf with more precise open-coded parser
Better errors while getting a smaller static executable.
(~16K less on amd64)
Diffstat:
2 files changed, 49 insertions(+), 15 deletions(-)
diff --git a/cmd/sha1sum.c b/cmd/sha1sum.c
@@ -6,9 +6,10 @@
#include "../lib/sha1.h" // sha1_*
#include "../lib/strconv.h" // bytes2hex
+#include <assert.h>
+#include <ctype.h> // isxdigit
#include <errno.h>
-#include <fcntl.h> // open, O_*
-#include <limits.h> // PATH_MAX
+#include <fcntl.h> // open, O_*
#include <stdbool.h>
#include <stdio.h> // fprintf
#include <stdlib.h> // free
@@ -61,25 +62,58 @@ check(FILE *file, char *filename)
errno = 0;
while((nread = getline(&line, &len, file)) > 0)
{
- char expect[SHA1SUM_LEN] = "";
- char target[PATH_MAX] = "";
+ assert(errno == 0);
+ if(line[nread - 1] == '\n') line[nread - 1] = '\0';
- static char *fmt = "%41[0-9A-Za-z]%*[* ]%" XSTR(PATH_MAX) "s%*[\n]";
- if(sscanf(line, fmt, &expect, &target) <= 0)
+ ssize_t i = 0;
+ for(; i < nread; i++)
{
- fprintf(stderr, "sha1sum: Error: Failed parsing line from file '%s': %s\n", filename, line);
+ if(isxdigit(line[i])) continue;
+ if(line[i] == ' ')
+ {
+ line[i] = '\0';
+ break;
+ }
+
+ fprintf(stderr,
+ "sha1sum: Error: Invalid character '%c' while reading hash in line: %s\n",
+ line[i],
+ line);
+ if(len > 0) free(line);
+ return -1;
+ }
+ if(line[i++] != '\0')
+ {
+ fprintf(stderr, "sha1sum: Error: Invalid line: %s\n", line);
if(len > 0) free(line);
return -1;
}
+ if(i != SHA1SUM_LEN)
+ {
+ fprintf(stderr,
+ "sha1sum: Error: Got %zd hexadecimal digits while expected %d for a SHA1\n",
+ i,
+ SHA1SUM_LEN);
+ if(len > 0) free(line);
+ return -1;
+ }
+
+ while(i < nread && line[i] == ' ')
+ i++;
+
+ if(i < nread && line[i] == '*') i++;
+
+ char *target = line + i;
+
int fd = open(target, O_RDONLY | O_NOCTTY);
if(fd < 0)
{
fprintf(stderr, "sha1sum: Error: Failed opening file '%s': %s\n", target, strerror(errno));
if(len > 0) free(line);
- return 1;
+ return -1;
}
int ret = posix_fadvise(fd, 0, 0, POSIX_FADV_SEQUENTIAL);
@@ -91,7 +125,7 @@ check(FILE *file, char *filename)
char got[SHA1SUM_LEN] = "";
if(sha1sum(fd, target, got) < 0) err = 1;
- if(memcmp(expect, got, SHA1SUM_LEN) == 0)
+ if(memcmp(line, got, SHA1SUM_LEN) == 0)
{
printf("%s: OK\n", target);
}
@@ -106,7 +140,7 @@ check(FILE *file, char *filename)
fprintf(stderr, "sha1sum: Failed closing file '%s': %s\n", filename, strerror(errno));
if(len > 0) free(line);
- return 1;
+ return -1;
}
}
if(nread < 0 && errno != 0)
diff --git a/test-cmd/sha1sum.sh b/test-cmd/sha1sum.sh
@@ -42,11 +42,11 @@ t --exit=1 --input='a9993e364706816aba3e25717850c26c9cd0d89d /var/empty/e/no/en
t --exit=1 --input='a9993e364706816aba3e25717850c26c9cd0d89d */var/empty/e/no/ent' 'xfail_bin_check:enoent' '-c' "sha1sum: Error: Failed opening file '/var/empty/e/no/ent': No such file or directory
"
-t --exit=1 --input="# $WD/inputs/empty" 'invalid_chars:#' '-c' "sha1sum: Error: Failed parsing line from file '<stdin>': # $WD/inputs/empty
+t --exit=1 --input="# $WD/inputs/empty" 'invalid_chars:#' '-c' "sha1sum: Error: Invalid character '#' while reading hash in line: # $WD/inputs/empty
"
t --exit=1 --input="a9993e364706816aba3e25717850c26c9cd0d89d" 'missing_file' '-c' "sha1sum: Error: Failed opening file '': No such file or directory
"
-t --exit=1 --input="a9993e364706816aba3e25717 $WD/inputs/empty" 'truncated_hash' '-c' "$WD/inputs/empty: FAILED
-"
-t --exit=1 --input="a9993e364706816aba3e25717850c26c9cd0d89da9993e364706816aba3e25717850c26c9cd0d89d $WD/inputs/empty" 'elongated_hash' '-c' "sha1sum: Error: Failed opening file '': No such file or directory
-"
+t --exit=1 --input="a9993e364706816aba3e25717 $WD/inputs/empty" 'truncated_hash' '-c' 'sha1sum: Error: Got 26 hexadecimal digits while expected 41 for a SHA1
+'
+t --exit=1 --input="a9993e364706816aba3e25717850c26c9cd0d89da9993e364706816aba3e25717850c26c9cd0d89d $WD/inputs/empty" 'elongated_hash' '-c' 'sha1sum: Error: Got 81 hexadecimal digits while expected 41 for a SHA1
+'