From a0dd7b608102bb04de414b47933f776827cf5427 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Mon, 28 Jul 2025 16:42:34 +1000 Subject: [PATCH] fdtput: Use strtol() in preference to sscanf() I find the exact semantics of scanf() always confusing, and mostly we use strtol() and similar functions instead. Switch fdtput to using strtol and similar functions instead of sscanf(). As well as being more in keeping with what we do in other places, this works around a FreeBSD bug[0], where sscanf(), but not strtol() parses "003" as having value 0. [0] https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=288440 Link: https://github.com/dgibson/dtc/issues/165 Signed-off-by: David Gibson --- fdtput.c | 34 +++++++++++++++++++++++++++++----- 1 file changed, 29 insertions(+), 5 deletions(-) diff --git a/fdtput.c b/fdtput.c index 825640c..05f2b93 100644 --- a/fdtput.c +++ b/fdtput.c @@ -9,6 +9,7 @@ #include #include #include +#include #include @@ -64,16 +65,12 @@ static int encode_value(struct display_info *disp, char **arg, int arg_count, int len; /* length of this cell/string/byte */ int ival; int upto; /* the number of bytes we have written to buf */ - char fmt[3]; upto = 0; if (disp->verbose) fprintf(stderr, "Decoding value:\n"); - fmt[0] = '%'; - fmt[1] = disp->type ? disp->type : 'd'; - fmt[2] = '\0'; for (; arg_count > 0; arg++, arg_count--, upto += len) { /* assume integer unless told otherwise */ if (disp->type == 's') @@ -94,7 +91,34 @@ static int encode_value(struct display_info *disp, char **arg, int arg_count, fprintf(stderr, "\tstring: '%s'\n", ptr); } else { fdt32_t *iptr = (fdt32_t *)ptr; - sscanf(*arg, fmt, &ival); + char *endptr; + + errno = 0; + switch (disp->type) { + case 'x': + ival = strtoul(*arg, &endptr, 16); + break; + case 'o': + ival = strtoul(*arg, &endptr, 8); + break; + case 'i': + ival = strtol(*arg, &endptr, 0); + break; + case 'u': + ival = strtoul(*arg, &endptr, 0); + break; + default: /* 0 or 'd' */ + ival = strtol(*arg, &endptr, 10); + } + + if (*endptr != '\0' || errno) { + if (disp->verbose) { + fprintf(stderr, + "Couldn't parse \"%s\" as an integer\n", + *arg); + } + return -1; + } if (len == 4) *iptr = cpu_to_fdt32(ival); else