Fix printf-family function not treating negative precisions as if they had been omitted

The C standard states that, within the context of a printf-family
function, when specifying the precision of a conversion specification:

> A negative precision argument is taken as if the precision were
> omitted.
- C Standard, 7.23.6.1. The fprintf function

Cosmopolitan currently fails to do so and treats a negative precision
as if it had a value of 0, which is non-conforming.

This patch fixes this.
This commit is contained in:
Gabriel Ravier 2023-03-23 21:58:14 +01:00
parent 792b1c84c0
commit e816e97762
2 changed files with 22 additions and 1 deletions

View file

@ -16,10 +16,11 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE. PERFORMANCE OF THIS SOFTWARE.
*/ */
#include "libc/fmt/fmt.h"
#include "libc/assert.h" #include "libc/assert.h"
#include "libc/errno.h" #include "libc/errno.h"
#include "libc/fmt/conv.h" #include "libc/fmt/conv.h"
#include "libc/fmt/fmt.h"
#include "libc/fmt/fmt.internal.h" #include "libc/fmt/fmt.internal.h"
#include "libc/fmt/internal.h" #include "libc/fmt/internal.h"
#include "libc/fmt/itoa.h" #include "libc/fmt/itoa.h"
@ -255,6 +256,7 @@ _Hide int __fmt(void *fn, void *arg, const char *format, va_list va) {
} }
if (prec < 0) { if (prec < 0) {
prec = 0; prec = 0;
flags &= ~FLAGS_PRECISION;
} }
// evaluate length field // evaluate length field

View file

@ -17,6 +17,7 @@
PERFORMANCE OF THIS SOFTWARE. PERFORMANCE OF THIS SOFTWARE.
*/ */
#include "libc/fmt/fmt.h" #include "libc/fmt/fmt.h"
#include "libc/limits.h" #include "libc/limits.h"
#include "libc/log/log.h" #include "libc/log/log.h"
#include "libc/math.h" #include "libc/math.h"
@ -84,6 +85,24 @@ TEST(fmt, b) {
} }
TEST(fmt, s) { TEST(fmt, s) {
EXPECT_STREQ("123456", _gc(xasprintf("%4.*s", -5, "123456")));
EXPECT_STREQ("123456789", _gc(xasprintf("%4.*s", -5, "123456789")));
EXPECT_STREQ("12345678901234567890",
_gc(xasprintf("%4.*s", -5, "12345678901234567890")));
EXPECT_STREQ("123456789012345678901234567890",
_gc(xasprintf("%4.*s", -5, "123456789012345678901234567890")));
EXPECT_STREQ(
"1234567890123456789012345678901234567890",
_gc(xasprintf("%4.*s", -5, "1234567890123456789012345678901234567890")));
EXPECT_STREQ(
"12345678901234567890123456789012345678901234567890",
_gc(xasprintf("%4.*s", -5,
"12345678901234567890123456789012345678901234567890")));
EXPECT_STREQ(
"123456789012345678901234567890123456789012345678901234567890",
_gc(xasprintf(
"%4.*s", -5,
"123456789012345678901234567890123456789012345678901234567890")));
EXPECT_STREQ("Wide character output test", EXPECT_STREQ("Wide character output test",
_gc(xasprintf("%S", L"Wide character output test"))); _gc(xasprintf("%S", L"Wide character output test")));
} }