|
|
Message-ID: <20251205043945.19881-1-idodo4nm@proton.me>
Date: Fri, 5 Dec 2025 11:39:45 +0700
From: mamutrahal269 <levrymvc@...il.com>
To: musl@...ts.openwall.com
Cc: mamutrahal269 <idodo4nm@...ton.me>
Subject: [PATCH] POSIX positional arg numbering (1-based) and multi-digit support in printf_core, raise NL_ARGMAX to 255
The positional argument parsing logic in printf_core was reworked: instead of only accepting single-digit
positional indices, the code now uses getint() to read multi-digit numbers and checks for the terminating $.
The old logic isdigit(s[1]) && s[2]=='$' was replaced with proper multi-digit parsing to support numbers
larger than 9. Additional validation was added to reject zero as an argument index and to detect overflow
when the index exceeds NL_ARGMAX. Similar multi-digit parsing was implemented for width and precision
arguments using * with positional indices. Finally, NL_ARGMAX was increased from 9 to 255 in limits.h
to match the expanded positional argument range.
Signed-off-by: mamutrahal269 <idodo4nm@...ton.me>
---
include/limits.h | 2 +-
src/stdio/vfprintf.c | 38 ++++++++++++++++++++++----------------
2 files changed, 23 insertions(+), 17 deletions(-)
diff --git a/include/limits.h b/include/limits.h
index 53a27b9d..760eb745 100644
--- a/include/limits.h
+++ b/include/limits.h
@@ -84,7 +84,7 @@
#define LINE_MAX 4096
#define RE_DUP_MAX 255
-#define NL_ARGMAX 9
+#define NL_ARGMAX 255
#define NL_MSGMAX 32767
#define NL_SETMAX 255
#define NL_TEXTMAX 2048
diff --git a/src/stdio/vfprintf.c b/src/stdio/vfprintf.c
index 514a44dd..e738e77f 100644
--- a/src/stdio/vfprintf.c
+++ b/src/stdio/vfprintf.c
@@ -429,11 +429,11 @@ static int getint(char **s) {
static int printf_core(FILE *f, const char *fmt, va_list *ap, union arg *nl_arg, int *nl_type)
{
- char *a, *z, *s=(char *)fmt;
+ char *a, *z, *s1, *s=(char *)fmt;
unsigned l10n=0, fl;
int w, p, xp;
union arg arg;
- int argpos;
+ int argpos, pos;
unsigned st, ps;
int cnt=0, l=0;
size_t i;
@@ -461,13 +461,14 @@ static int printf_core(FILE *f, const char *fmt, va_list *ap, union arg *nl_arg,
if (f) out(f, a, l);
if (l) continue;
- if (isdigit(s[1]) && s[2]=='$') {
+ s1 = ++s;
+ if ((argpos = getint(&s1)) >= 0 && *s1=='$') {
+ if (argpos > NL_ARGMAX) goto overflow;
+ if (!argpos) goto inval;
l10n=1;
- argpos = s[1]-'0';
- s+=3;
+ s = s1 + 1;
} else {
argpos = -1;
- s++;
}
/* Read modifier flags */
@@ -476,27 +477,32 @@ static int printf_core(FILE *f, const char *fmt, va_list *ap, union arg *nl_arg,
/* Read field width */
if (*s=='*') {
- if (isdigit(s[1]) && s[2]=='$') {
+ s1 = ++s;
+ if ((pos = getint(&s1)) >= 0 && *s1=='$') {
+ if (pos > NL_ARGMAX) goto overflow;
+ if (!pos) goto inval;
l10n=1;
- if (!f) nl_type[s[1]-'0'] = INT, w = 0;
- else w = nl_arg[s[1]-'0'].i;
- s+=3;
+ s = s1 + 1;
+ if (!f) nl_type[pos] = INT, w = 0;
+ else w = nl_arg[pos].i;
} else if (!l10n) {
w = f ? va_arg(*ap, int) : 0;
- s++;
} else goto inval;
if (w<0) fl|=LEFT_ADJ, w=-w;
} else if ((w=getint(&s))<0) goto overflow;
/* Read precision */
if (*s=='.' && s[1]=='*') {
- if (isdigit(s[2]) && s[3]=='$') {
- if (!f) nl_type[s[2]-'0'] = INT, p = 0;
- else p = nl_arg[s[2]-'0'].i;
- s+=4;
+ s+=2;
+ s1 = s;
+ if ((pos = getint(&s1)) >= 0 && *s1=='$') {
+ if (pos > NL_ARGMAX) goto overflow;
+ if (!pos) goto inval;
+ s = s1 + 1;
+ if (!f) nl_type[pos] = INT, p = 0;
+ else p = nl_arg[pos].i;
} else if (!l10n) {
p = f ? va_arg(*ap, int) : 0;
- s+=2;
} else goto inval;
xp = (p>=0);
} else if (*s=='.') {
--
2.47.3
Powered by blists - more mailing lists
Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.