diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2020-03-16 14:13:13 -0300 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2020-03-16 14:13:13 -0300 |
commit | 513559cc4760392b6fa33754c516683ef49dba22 (patch) | |
tree | 7080bdf0e31f0ce14545a0e8a68daff3b36cec62 | |
parent | e4607523234f16ed9ed0436340b9315377dbfe7f (diff) | |
download | lua-github-513559cc4760392b6fa33754c516683ef49dba22.tar.gz |
Fixed bug in 'string.format("%p")'
The string "(null)" used for non-collectable values must be printed as a
string, not as a pointer. (Bug introduced in commit e0cbaa50fa7).
-rw-r--r-- | lstrlib.c | 6 | ||||
-rw-r--r-- | ltests.c | 3 | ||||
-rw-r--r-- | testes/strings.lua | 18 |
3 files changed, 19 insertions, 8 deletions
@@ -1271,8 +1271,10 @@ static int str_format (lua_State *L) { } case 'p': { const void *p = lua_topointer(L, arg); - if (p == NULL) - p = "(null)"; /* NULL not a valid parameter in ISO C 'printf' */ + if (p == NULL) { /* avoid calling 'printf' with argument NULL */ + p = "(null)"; /* result */ + form[strlen(form) - 1] = 's'; /* format it as a string */ + } nb = l_sprintf(buff, maxitem, form, p); break; } @@ -131,8 +131,7 @@ static void warnf (void *ud, const char *msg, int tocont) { if (buff[0] != '#' && onoff) /* unexpected warning? */ badexit("Unexpected warning in test mode: %s\naborting...\n", buff, NULL); - /* else */ /* FALLTHROUGH */ - } + } /* FALLTHROUGH */ case 1: { /* allow */ if (onoff) fprintf(stderr, "Lua warning: %s\n", buff); /* print warning */ diff --git a/testes/strings.lua b/testes/strings.lua index 2ce3ebc3..4a10857e 100644 --- a/testes/strings.lua +++ b/testes/strings.lua @@ -158,28 +158,38 @@ do -- tests for '%p' format -- not much to test, as C does not specify what '%p' does. -- ("The value of the pointer is converted to a sequence of printing -- characters, in an implementation-defined manner.") - local null = string.format("%p", nil) - assert(string.format("%p", {}) ~= null) + local null = "(null)" -- nulls are formatted by Lua assert(string.format("%p", 4) == null) assert(string.format("%p", true) == null) + assert(string.format("%p", nil) == null) + assert(string.format("%p", {}) ~= null) assert(string.format("%p", print) ~= null) assert(string.format("%p", coroutine.running()) ~= null) assert(string.format("%p", io.stdin) ~= null) assert(string.format("%p", io.stdin) == string.format("%p", io.stdin)) + assert(string.format("%p", print) == string.format("%p", print)) + assert(string.format("%p", print) ~= string.format("%p", assert)) + + assert(#string.format("%90p", {}) == 90) + assert(#string.format("%-60p", {}) == 60) + assert(string.format("%10p", false) == string.rep(" ", 10 - #null) .. null) + assert(string.format("%-12p", 1.5) == null .. string.rep(" ", 12 - #null)) + do local t1 = {}; local t2 = {} assert(string.format("%p", t1) ~= string.format("%p", t2)) end + do -- short strings are internalized local s1 = string.rep("a", 10) - local s2 = string.rep("a", 10) + local s2 = string.rep("aa", 5) assert(string.format("%p", s1) == string.format("%p", s2)) end + do -- long strings aren't internalized local s1 = string.rep("a", 300); local s2 = string.rep("a", 300) assert(string.format("%p", s1) ~= string.format("%p", s2)) end - assert(#string.format("%90p", {}) == 90) end x = '"ílo"\n\\' |