|
@@ -300,6 +300,46 @@ static void stbsp__lead_sign(stbsp__uint32 fl, char *sign)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+static STBSP__ASAN stbsp__uint32 stbsp__strlen_limited(char const *s, stbsp__uint32 limit)
|
|
|
+{
|
|
|
+ char const * sn = s;
|
|
|
+
|
|
|
+ // get up to 4-byte alignment
|
|
|
+ for (;;) {
|
|
|
+ if (((stbsp__uintptr)sn & 3) == 0)
|
|
|
+ break;
|
|
|
+
|
|
|
+ if (!limit || *sn == 0)
|
|
|
+ return (stbsp__uint32)(sn - s);
|
|
|
+
|
|
|
+ ++sn;
|
|
|
+ --limit;
|
|
|
+ }
|
|
|
+
|
|
|
+ // scan over 4 bytes at a time to find terminating 0
|
|
|
+ // this will intentionally scan up to 3 bytes past the end of buffers,
|
|
|
+ // but becase it works 4B aligned, it will never cross page boundaries
|
|
|
+ // (hence the STBSP__ASAN markup; the over-read here is intentional
|
|
|
+ // and harmless)
|
|
|
+ while (limit >= 4) {
|
|
|
+ stbsp__uint32 v = *(stbsp__uint32 *)sn;
|
|
|
+ // bit hack to find if there's a 0 byte in there
|
|
|
+ if ((v - 0x01010101) & (~v) & 0x80808080UL)
|
|
|
+ break;
|
|
|
+
|
|
|
+ sn += 4;
|
|
|
+ limit -= 4;
|
|
|
+ }
|
|
|
+
|
|
|
+ // handle the last few characters to find actual size
|
|
|
+ while (limit && *sn) {
|
|
|
+ ++sn;
|
|
|
+ --limit;
|
|
|
+ }
|
|
|
+
|
|
|
+ return (stbsp__uint32)(sn - s);
|
|
|
+}
|
|
|
+
|
|
|
STBSP__PUBLICDEF int STB_SPRINTF_DECORATE(vsprintfcb)(STBSP_SPRINTFCB *callback, void *user, char *buf, char const *fmt, va_list va)
|
|
|
{
|
|
|
static char hex[] = "0123456789abcdefxp";
|
|
@@ -543,37 +583,9 @@ STBSP__PUBLICDEF int STB_SPRINTF_DECORATE(vsprintfcb)(STBSP_SPRINTFCB *callback,
|
|
|
s = va_arg(va, char *);
|
|
|
if (s == 0)
|
|
|
s = (char *)"null";
|
|
|
- // get the length
|
|
|
- sn = s;
|
|
|
- for (;;) {
|
|
|
- if ((((stbsp__uintptr)sn) & 3) == 0)
|
|
|
- break;
|
|
|
- lchk:
|
|
|
- if (sn[0] == 0)
|
|
|
- goto ld;
|
|
|
- ++sn;
|
|
|
- }
|
|
|
- n = 0xffffffff;
|
|
|
- if (pr >= 0) {
|
|
|
- n = (stbsp__uint32)(sn - s);
|
|
|
- if (n >= (stbsp__uint32)pr)
|
|
|
- goto ld;
|
|
|
- n = ((stbsp__uint32)(pr - n)) >> 2;
|
|
|
- }
|
|
|
- while (n) {
|
|
|
- stbsp__uint32 v = *(stbsp__uint32 *)sn;
|
|
|
- if ((v - 0x01010101) & (~v) & 0x80808080UL)
|
|
|
- goto lchk;
|
|
|
- sn += 4;
|
|
|
- --n;
|
|
|
- }
|
|
|
- goto lchk;
|
|
|
- ld:
|
|
|
-
|
|
|
- l = (stbsp__uint32)(sn - s);
|
|
|
- // clamp to precision
|
|
|
- if (l > (stbsp__uint32)pr)
|
|
|
- l = pr;
|
|
|
+ // get the length, limited to desired precision
|
|
|
+ // always limit to ~0u chars since our counts are 32b
|
|
|
+ l = stbsp__strlen_limited(s, (pr >= 0) ? pr : ~0u);
|
|
|
lead[0] = 0;
|
|
|
tail[0] = 0;
|
|
|
pr = 0;
|