From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail-wm1-f49.google.com (mail-wm1-f49.google.com [209.85.128.49]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C63B0429826 for ; Fri, 6 Feb 2026 19:11:32 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.49 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770405093; cv=none; b=ZXXuTa37DjR/coofSJV1rRWUk81meN4ymtO6VeSs/FkNzAR1i6d69ii+V7mFgjENRK+dQoHZTu3DSpukHfWWgz5DlPDoAXxxBHZebHYmZQC1Dhf9hWkh9kUvnb1hRb3/Y6GJbt4hS2MNN6Tn0YVYPZ+Ld/kJZ/HUslasU4OaPO8= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770405093; c=relaxed/simple; bh=3KrNHAv8EGUKDcXFqqiN9PYqRNaSOy0/Sddepr2uQ+c=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=mV8hlbEo0b6OtE8g5s1HRV2kCINO+DCoWWLGykcVR10FFqv1mzP/Tv11kR2SWxKCWZzgOyaypboFu1M77RC9lbuWK12Jw0foUUvzQU0OPoQiWXawT+r4Kx2MVb+SiezDcZJJ9oh3EiwfSLSts0r4zaRqHIwV7o84wEBkh+Gmz4U= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=ZMAnIv1a; arc=none smtp.client-ip=209.85.128.49 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="ZMAnIv1a" Received: by mail-wm1-f49.google.com with SMTP id 5b1f17b1804b1-4806fbc6bf3so12022965e9.2 for ; Fri, 06 Feb 2026 11:11:32 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1770405091; x=1771009891; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=KtD2h9yuGx4JxzHZQAOuJuLEHagfIt7X0NUGbcfnCrU=; b=ZMAnIv1aU9ZAvOkoZKSzvq1bIxRHVWdz7kXwA6a0YIsXE3lD4j1ferFtd0GV9jv4Tj Yehojxj6wu7dDQRfCgGIuPprTIYbjHxN9jrALnZ7P/rNctk7XzbsShCCUqk9wTdo7Mwb b81y/E8lRWamtxKbQDAXuniZBo4J4lQqhz+KxeUsYNDrtA/YSrpGlEcQEdRZQgZG8bFn uilID4cq07JgT1xByYE8JdyIho9ILrbbRRJlM5FkePDagVNsZPlWfxma53AsAl9I1VN8 /XvKMTiHmgfLx5TUsMzExthO2T2+0lIi1Mp0gvq74Ft3J9HzsjbCIT4v4vpPvtT+xj7D tyfQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1770405091; x=1771009891; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=KtD2h9yuGx4JxzHZQAOuJuLEHagfIt7X0NUGbcfnCrU=; b=OkblDe/X7hflR6i6XSENuMgVH4gIS8+9/fz7I+ejDfK1wg+sVQnjRnp2BM2GPJE8yD zgVSsX4UMFmrnPKmyVTkhpeelTCbGvF5SPTXkJEgcA7LK4N9cnvfckmuqlprqbOr1g33 ImS7dIqXol4+eh1eVCzVA8PqJULNp0h7HTBDNs2PRj5lz37wsid/Dm8yyEyXs4iJf/d6 uP35cH12J+YGgxmELrC57WXU9tgVFXhHl9rae97q9COHtqpBiNSYVcRZiFvadBQuI5Lj 6yM2n//uSP9PUj6rUmyZMxvXBRwrvEwvRi7DNAJ9vnce9AR2Q/rwR3qC2/yO9BnI5JZC rvPg== X-Forwarded-Encrypted: i=1; AJvYcCVQNJ6xKTK4RJhLUmORexpNNEA4+7+6aR1q04fTf0+T6NrUpYOiT/O5TpcmHBDO1BeXU0Ly5mFhhdRSoSU=@vger.kernel.org X-Gm-Message-State: AOJu0YyVIB5ITJjCBqBUk260dSleqohs48p7NLyQyL+iDZeM19SF+szL 4PMMyBiEKDOpkpp7LOqc8et78ViOY2nog1WAC3sFcHBoKivbZ7k+GGla X-Gm-Gg: AZuq6aJskZKedj0Hq2QfehbpCTuMflBIJNjZKG9whSKgLWGl4OU2DZpgA3Pjsiw1MK9 hy11aX8pv5uI7CJFtycMesEORV7wjQY2EmVG/0t3+3T0E5/dK6oYI/cxORyyPJqOvc/spqGB1FA vYZa0YJI6k7kabvjsGDsLSx/qKPg1yOaO/wH8VWxN8NXkcfur81rrR4q07sIdcOCAEJRoLBYyEv huekH/sVo9faM0nA5JdgHEz7CXKod9G3sZjoDrXEjSnA4wtVmgzQUzsgpwg4GZMwLw79aMvsTo1 8SamP4VMmhNbPjp5zBRe0pDo3sTtlWUcXXHl35siftGpUuFdAU9zZcZiW9nyyancjdR2POVD+sl Hxe7i+22c3yK14ubaqC/BaIhN+94RQOnDtuAp1LS9A98qYp3BdcqDZvYQBLtIvNVGJ6l/Kvk5RS eJ5sGuftTgu6R/fQTDzAnQ/apIeKaFAGyIL6yDQtegE9SQjYezg0QZpbm1F4nduM5P9epYVzQV X-Received: by 2002:a05:600c:c16d:b0:475:dd89:acb with SMTP id 5b1f17b1804b1-48320216097mr51901915e9.22.1770405091142; Fri, 06 Feb 2026 11:11:31 -0800 (PST) Received: from snowdrop.snailnet.com (82-69-66-36.dsl.in-addr.zen.co.uk. [82.69.66.36]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-4362972fb81sm8703681f8f.20.2026.02.06.11.11.30 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 06 Feb 2026 11:11:30 -0800 (PST) From: david.laight.linux@gmail.com To: Willy Tarreau , =?UTF-8?q?Thomas=20Wei=C3=9Fschuh?= , linux-kernel@vger.kernel.org, Cheng Li Cc: David Laight Subject: [PATCH v2 next 02/11] tools/nolibc/printf: Move snprintf length check to callback Date: Fri, 6 Feb 2026 19:11:12 +0000 Message-Id: <20260206191121.3602-3-david.laight.linux@gmail.com> X-Mailer: git-send-email 2.39.5 In-Reply-To: <20260206191121.3602-1-david.laight.linux@gmail.com> References: <20260206191121.3602-1-david.laight.linux@gmail.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit From: David Laight Move output truncation to the snprintf() callback. This simplifies the main code and ensures the truncation will be correct when left-alignment is added. Add a zero length callback to 'finalise' the buffer rather than doing it in snprintf() itself. Signed-off-by: David Laight --- Changes for v2: - Formally patch 1 - Add comments about the final callback. tools/include/nolibc/stdio.h | 68 ++++++++++++++++++++++-------------- 1 file changed, 41 insertions(+), 27 deletions(-) diff --git a/tools/include/nolibc/stdio.h b/tools/include/nolibc/stdio.h index f162cc697a73..36733ecd4261 100644 --- a/tools/include/nolibc/stdio.h +++ b/tools/include/nolibc/stdio.h @@ -245,15 +245,15 @@ char *fgets(char *s, int size, FILE *stream) * - %s * - unknown modifiers are ignored. */ -typedef int (*__nolibc_printf_cb)(intptr_t state, const char *buf, size_t size); +typedef int (*__nolibc_printf_cb)(void *state, const char *buf, size_t size); -static __attribute__((unused, format(printf, 4, 0))) -int __nolibc_printf(__nolibc_printf_cb cb, intptr_t state, size_t n, const char *fmt, va_list args) +static __attribute__((unused, format(printf, 3, 0))) +int __nolibc_printf(__nolibc_printf_cb cb, void *state, const char *fmt, va_list args) { char escape, lpref, ch; unsigned long long v; unsigned int written, width; - size_t len, ofs, w; + size_t len, ofs; char tmpbuf[21]; const char *outstr; @@ -355,17 +355,13 @@ int __nolibc_printf(__nolibc_printf_cb cb, intptr_t state, size_t n, const char outstr = fmt; len = ofs - 1; flush_str: - if (n) { - w = len < n ? len : n; - n -= w; - while (width-- > w) { - if (cb(state, " ", 1) != 0) - return -1; - written += 1; - } - if (cb(state, outstr, w) != 0) + while (width-- > len) { + if (cb(state, " ", 1) != 0) return -1; + written += 1; } + if (cb(state, outstr, len) != 0) + return -1; written += len; do_escape: @@ -378,18 +374,23 @@ int __nolibc_printf(__nolibc_printf_cb cb, intptr_t state, size_t n, const char /* literal char, just queue it */ } + + /* Flush/terminate any buffer. */ + if (cb(state, NULL, 0) != 0) + return -1; + return written; } -static int __nolibc_fprintf_cb(intptr_t state, const char *buf, size_t size) +static int __nolibc_fprintf_cb(void *stream, const char *buf, size_t size) { - return _fwrite(buf, size, (FILE *)state); + return size ? _fwrite(buf, size, stream) : 0; } static __attribute__((unused, format(printf, 2, 0))) int vfprintf(FILE *stream, const char *fmt, va_list args) { - return __nolibc_printf(__nolibc_fprintf_cb, (intptr_t)stream, SIZE_MAX, fmt, args); + return __nolibc_printf(__nolibc_fprintf_cb, stream, fmt, args); } static __attribute__((unused, format(printf, 1, 0))) @@ -447,26 +448,39 @@ int dprintf(int fd, const char *fmt, ...) return ret; } -static int __nolibc_sprintf_cb(intptr_t _state, const char *buf, size_t size) +struct __nolibc_sprintf_cb_state { + char *buf; + size_t size; +}; + +static int __nolibc_sprintf_cb(void *v_state, const char *buf, size_t size) { - char **state = (char **)_state; + struct __nolibc_sprintf_cb_state *state = v_state; + char *tgt; - memcpy(*state, buf, size); - *state += size; + if (size >= state->size) { + if (state->size <= 1) + return 0; + size = state->size - 1; + } + tgt = state->buf; + if (size) { + state->size -= size; + state->buf = tgt + size; + memcpy(tgt, buf, size); + } else { + /* In particular from cb(NULL, 0) at the end of __nolibc_printf(). */ + *tgt = '\0'; + } return 0; } static __attribute__((unused, format(printf, 3, 0))) int vsnprintf(char *buf, size_t size, const char *fmt, va_list args) { - char *state = buf; - int ret; + struct __nolibc_sprintf_cb_state state = { .buf = buf, .size = size }; - ret = __nolibc_printf(__nolibc_sprintf_cb, (intptr_t)&state, size, fmt, args); - if (ret < 0) - return ret; - buf[(size_t)ret < size ? (size_t)ret : size - 1] = '\0'; - return ret; + return __nolibc_printf(__nolibc_sprintf_cb, &state, fmt, args); } static __attribute__((unused, format(printf, 3, 4))) -- 2.39.5