summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2020-03-16 14:13:13 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2020-03-16 14:13:13 -0300
commit513559cc4760392b6fa33754c516683ef49dba22 (patch)
tree7080bdf0e31f0ce14545a0e8a68daff3b36cec62
parente4607523234f16ed9ed0436340b9315377dbfe7f (diff)
downloadlua-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.c6
-rw-r--r--ltests.c3
-rw-r--r--testes/strings.lua18
3 files changed, 19 insertions, 8 deletions
diff --git a/lstrlib.c b/lstrlib.c
index 28df2d45..2ba8bde4 100644
--- a/lstrlib.c
+++ b/lstrlib.c
@@ -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;
}
diff --git a/ltests.c b/ltests.c
index 76a6ea9b..7e6d8610 100644
--- a/ltests.c
+++ b/ltests.c
@@ -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\\'