|  | 
|  | 1 | +--[[ | 
|  | 2 | +SPDX-License-Identifier: ISC | 
|  | 3 | +Copyright (c) 2023-2025, Sergey Bronnikov. | 
|  | 4 | +
 | 
|  | 5 | +6.4 – String Manipulation | 
|  | 6 | +https://www.lua.org/manual/5.3/manual.html#6.4 | 
|  | 7 | +
 | 
|  | 8 | +stack-buffer-overflow in lj_strfmt_wfnum, | 
|  | 9 | +https://github.com/LuaJIT/LuaJIT/issues/1149 | 
|  | 10 | +string.format("%7g",0x1.144399609d407p+401) | 
|  | 11 | +
 | 
|  | 12 | +string.format %c bug, | 
|  | 13 | +https://github.com/LuaJIT/LuaJIT/issues/378 | 
|  | 14 | +
 | 
|  | 15 | +string.format doesn't take current locale decimal separator into account, | 
|  | 16 | +https://github.com/LuaJIT/LuaJIT/issues/673 | 
|  | 17 | +
 | 
|  | 18 | +string.format("%f") can cause a buffer overflow (only when | 
|  | 19 | +'lua_Number' is long double!), | 
|  | 20 | +https://www.lua.org/bugs.html#5.3.0-1 | 
|  | 21 | +
 | 
|  | 22 | +string.format may get buffer as an argument when there are missing | 
|  | 23 | +arguments and format string is too long, | 
|  | 24 | +https://www.lua.org/bugs.html#5.1.4-7 | 
|  | 25 | +
 | 
|  | 26 | +string.format("%") may read past the string, | 
|  | 27 | +https://www.lua.org/bugs.html#5.1.1-3 | 
|  | 28 | +
 | 
|  | 29 | +Option '%q' in string.formatE does not handle '\r' correctly, | 
|  | 30 | +https://www.lua.org/bugs.html#5.1-4 | 
|  | 31 | +
 | 
|  | 32 | +FFI: Support FFI numbers in string.format() and buf:putf(), | 
|  | 33 | +https://github.com/LuaJIT/LuaJIT/commit/1b7171c3 | 
|  | 34 | +
 | 
|  | 35 | +[0014] CRASH detected in lj_ir_kgc due to a fault at or | 
|  | 36 | +near 0x00007ff7f3274008 leading to SIGSEGV, | 
|  | 37 | +https://github.com/LuaJIT/LuaJIT/issues/1203 | 
|  | 38 | +
 | 
|  | 39 | +Synopsis: string.format(formatstring, ...) | 
|  | 40 | +]] | 
|  | 41 | + | 
|  | 42 | + | 
|  | 43 | +local luzer = require("luzer") | 
|  | 44 | +local test_lib = require("lib") | 
|  | 45 | + | 
|  | 46 | +local specifiers = { | 
|  | 47 | +    "a", | 
|  | 48 | +    "A", | 
|  | 49 | +    "c", | 
|  | 50 | +    "d", | 
|  | 51 | +    "e", | 
|  | 52 | +    "E", | 
|  | 53 | +    "f", | 
|  | 54 | +    "g", | 
|  | 55 | +    "G", | 
|  | 56 | +    "i", | 
|  | 57 | +    "o", | 
|  | 58 | +    "p", | 
|  | 59 | +    "q", | 
|  | 60 | +    "s", | 
|  | 61 | +    "u", | 
|  | 62 | +    "x", | 
|  | 63 | +    "X", | 
|  | 64 | +} | 
|  | 65 | + | 
|  | 66 | +local function TestOneInput(buf, _size) | 
|  | 67 | +    local fdp = luzer.FuzzedDataProvider(buf) | 
|  | 68 | +    local spec = fdp:oneof(specifiers) | 
|  | 69 | +    local format_string = ("%%%s"):format(spec) | 
|  | 70 | +    local max_len = fdp:consume_integer(1, 10000) | 
|  | 71 | +    local str = fdp:consume_string(1, max_len) | 
|  | 72 | + | 
|  | 73 | +    os.setlocale(test_lib.random_locale(fdp), "all") | 
|  | 74 | +    local ok, res = pcall(string.format, format_string, str) | 
|  | 75 | +    assert(type(res) == "string") | 
|  | 76 | +    if ok then | 
|  | 77 | +        assert((format_string):format(str) == string.format(format_string, str)) | 
|  | 78 | +    end | 
|  | 79 | +end | 
|  | 80 | + | 
|  | 81 | +local args = { | 
|  | 82 | +    artifact_prefix = "string_format_", | 
|  | 83 | +} | 
|  | 84 | +luzer.Fuzz(TestOneInput, nil, args) | 
0 commit comments