From nobody Thu Apr 2 20:28:30 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C5E123D0906; Fri, 20 Mar 2026 16:27:32 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774024052; cv=none; b=b1ryBHM72un337b3/ywZ2J02VbwXCcHS462yJCNckHbK+IkudpSIFC5mS/nowpInoD19JVPkbsgjapKP8zLP9EWdnaQMhb+A1VTF+AN7qPmMYosMSfGchTRLZqxUcgHkTDREg0oacc2pSLknqDdSinL4ic+DIbSPjTkuJz2yGFg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774024052; c=relaxed/simple; bh=DuMyvK6DFgnd0Ej9rOVYnF6v/NLqjEekBfg4n169DBk=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=CHkDgTdqM9iL8qhWOM4sJqoPB9pLUprtQlEZP3DzM822VAHhArTEMf6z2wSqql664+5okEr8yW5uj7Teib34Qy3cglcNRRHTmUJv38u2kzXZz4BWg47vBY16Nw3tobMxX3HHrSkfE08RmbbWFUMY/B+0RH6DXh6f6ziDdfMdetI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=gBbfkR5s; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="gBbfkR5s" Received: by smtp.kernel.org (Postfix) with ESMTPS id 94236C2BCB0; Fri, 20 Mar 2026 16:27:32 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1774024052; bh=DuMyvK6DFgnd0Ej9rOVYnF6v/NLqjEekBfg4n169DBk=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=gBbfkR5sjygv1DwCJn5M2Akz6fpgNpEkUYAz3wsaBGB2G2dKoosf5pXlsCnNGrXyG ixjwtd+LX+25W4qlRMIC4iIonA3eTq4dzpb7AStEc0y6q/oJ2uDARl09D/JVtwE98L fOVWxARXdPhtK2oPhlzhp9Q4rCYkpbVG5513kyGGBlryabPoSrq0bMxPq9yKUDpM+3 KpiZwUyDxJl3+ncPstew+kvueIcQ7fO5uK9B9ZUzRy6lhqosMSN0L1VobH4y+qtB9v 4FshPlet03KWHSNtzLZ3327jiA97f0iFPLLBvdv2/InVqs7ohJvtkS6OOutb2PDZEd OKdF53pp06alQ== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 868E010987AA; Fri, 20 Mar 2026 16:27:32 +0000 (UTC) From: Rodrigo Alencar via B4 Relay Date: Fri, 20 Mar 2026 16:27:27 +0000 Subject: [PATCH v9 2/9] lib: vsprintf: export simple_strntoull() in a safe prototype Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260320-adf41513-iio-driver-v9-2-132f0d076374@analog.com> References: <20260320-adf41513-iio-driver-v9-0-132f0d076374@analog.com> In-Reply-To: <20260320-adf41513-iio-driver-v9-0-132f0d076374@analog.com> To: linux-kernel@vger.kernel.org, linux-iio@vger.kernel.org, devicetree@vger.kernel.org, linux-doc@vger.kernel.org Cc: Jonathan Cameron , David Lechner , Andy Shevchenko , Lars-Peter Clausen , Michael Hennerich , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Jonathan Corbet , Andrew Morton , Petr Mladek , Steven Rostedt , Andy Shevchenko , Rasmus Villemoes , Sergey Senozhatsky , Shuah Khan , Rodrigo Alencar X-Mailer: b4 0.14.3 X-Developer-Signature: v=1; a=ed25519-sha256; t=1774024051; l=4961; i=rodrigo.alencar@analog.com; s=default; h=from:subject:message-id; bh=y9XuvOW7WnSOw9U6xKx4a7qJToIhm1Kjwj+aTkUEMP0=; b=7BHPg3COnAmow6RIibVkXv2I8hJnFf5WiTTNEZgjF+DwrsPlq0Yx97QGmtJHuZW3yAJqbXwvH NGDcvO2lErjAS6pRDT6Xu90PlZhbSDwoHRsCVBbU0PtBOavW72Ya7sL X-Developer-Key: i=rodrigo.alencar@analog.com; a=ed25519; pk=ULeHbgU/OYh/PG/4anHDfLgldFItQHAhOktYRVLMFRo= X-Endpoint-Received: by B4 Relay for rodrigo.alencar@analog.com/default with auth_id=561 X-Original-From: Rodrigo Alencar Reply-To: rodrigo.alencar@analog.com From: Rodrigo Alencar Expose simple_strntoull(), by addressing its FIXME, i.e. its prototype is slightly changed so that -ERANGE or -EINVAL can be evaluated by the user. Flow of the function is not changed and error value is returned in the end. Unsafe internal wrapper is created to reduce amount of changes. Signed-off-by: Rodrigo Alencar --- include/linux/kstrtox.h | 4 ++++ lib/vsprintf.c | 59 +++++++++++++++++++++++++++++++++++++++++----= ---- 2 files changed, 54 insertions(+), 9 deletions(-) diff --git a/include/linux/kstrtox.h b/include/linux/kstrtox.h index 6ea897222af1..5e161073121f 100644 --- a/include/linux/kstrtox.h +++ b/include/linux/kstrtox.h @@ -148,4 +148,8 @@ extern long simple_strtol(const char *,char **,unsigned= int); extern unsigned long long simple_strtoull(const char *,char **,unsigned in= t); extern long long simple_strtoll(const char *,char **,unsigned int); =20 +extern ssize_t __must_check simple_strntoull(const char *startp, const cha= r **endp, + unsigned int base, size_t max_chars, + unsigned long long *res); + #endif /* _LINUX_KSTRTOX_H */ diff --git a/lib/vsprintf.c b/lib/vsprintf.c index 800b8ac49f53..6fb880f4013b 100644 --- a/lib/vsprintf.c +++ b/lib/vsprintf.c @@ -75,25 +75,66 @@ enum hash_pointers_policy { }; static enum hash_pointers_policy hash_pointers_mode __initdata; =20 +/** + * simple_strntoull - convert a string to an unsigned long long with a cha= racter limit + * + * @startp: The start of the string + * @endp: A pointer to the end of the parsed string will be placed here + * @base: The number base to use + * @max_chars: The maximum number of characters to parse + * @res: Where to write the result of the conversion on success + * + * Returns amount of processed characters on success, -ERANGE on overflow = and + * -EINVAL on parsing error. + */ noinline -static unsigned long long simple_strntoull(const char *startp, char **endp= , unsigned int base, size_t max_chars) +ssize_t simple_strntoull(const char *startp, const char **endp, + unsigned int base, size_t max_chars, + unsigned long long *res) { const char *cp; - unsigned long long result =3D 0ULL; size_t prefix_chars; unsigned int rv; + ssize_t ret; =20 cp =3D _parse_integer_fixup_radix(startp, &base); prefix_chars =3D cp - startp; if (prefix_chars < max_chars) { - rv =3D _parse_integer_limit(cp, base, &result, max_chars - prefix_chars); - /* FIXME */ + rv =3D _parse_integer_limit(cp, base, res, max_chars - prefix_chars); + if (rv & KSTRTOX_OVERFLOW) + ret =3D -ERANGE; + else if (rv =3D=3D 0) + ret =3D -EINVAL; + else + ret =3D rv + prefix_chars; cp +=3D (rv & ~KSTRTOX_OVERFLOW); } else { /* Field too short for prefix + digit, skip over without converting */ cp =3D startp + max_chars; + ret =3D -EINVAL; + *res =3D 0ULL; } =20 + if (endp) + *endp =3D cp; + + return ret; +} +EXPORT_SYMBOL(simple_strntoull); + +/* unsafe_strntoull ignores simple_strntoull() return value and endp const= qualifier */ +inline +static unsigned long long unsafe_strntoull(const char *startp, char **endp, + unsigned int base, size_t max_chars) +{ + unsigned long long result; + const char *cp; + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-result" + simple_strntoull(startp, &cp, base, max_chars, &result); +#pragma GCC diagnostic pop + if (endp) *endp =3D (char *)cp; =20 @@ -111,7 +152,7 @@ static unsigned long long simple_strntoull(const char *= startp, char **endp, unsi noinline unsigned long long simple_strtoull(const char *cp, char **endp, unsigned i= nt base) { - return simple_strntoull(cp, endp, base, INT_MAX); + return unsafe_strntoull(cp, endp, base, INT_MAX); } EXPORT_SYMBOL(simple_strtoull); =20 @@ -132,7 +173,7 @@ EXPORT_SYMBOL(simple_strtoul); unsigned long simple_strntoul(const char *cp, char **endp, unsigned int ba= se, size_t max_chars) { - return simple_strntoull(cp, endp, base, max_chars); + return unsafe_strntoull(cp, endp, base, max_chars); } EXPORT_SYMBOL(simple_strntoul); =20 @@ -163,9 +204,9 @@ static long long simple_strntoll(const char *cp, char *= *endp, unsigned int base, * and the content of *cp is irrelevant. */ if (*cp =3D=3D '-' && max_chars > 0) - return -simple_strntoull(cp + 1, endp, base, max_chars - 1); + return -unsafe_strntoull(cp + 1, endp, base, max_chars - 1); =20 - return simple_strntoull(cp, endp, base, max_chars); + return unsafe_strntoull(cp, endp, base, max_chars); } =20 /** @@ -3670,7 +3711,7 @@ int vsscanf(const char *buf, const char *fmt, va_list= args) val.s =3D simple_strntoll(str, &next, base, field_width >=3D 0 ? field_width : INT_MAX); else - val.u =3D simple_strntoull(str, &next, base, + val.u =3D unsafe_strntoull(str, &next, base, field_width >=3D 0 ? field_width : INT_MAX); =20 switch (qualifier) { --=20 2.43.0