http.server error Traceback[httpserver]: /usr/local/lib/prosody/modules/mod_http_files.lua:115: bad argument #1 to 'format' (not a non-negative number in proper range)
stack traceback:
[C]: in function 'format'
/usr/local/lib/prosody/modules/mod_http_files.lua:115: in function </usr/local/lib/prosody/modules/mod_http_files.lua:96>
(...tail calls...)
/usr/local/lib/prosody/util/events.lua:79: in function </usr/local/lib/prosody/util/events.lua:75>
(...tail calls...)
/usr/local/lib/prosody/net/http/server.lua:248: in function </usr/local/lib/prosody/net/http/server.lua:176>
[C]: in function 'xpcall'
/usr/local/lib/prosody/net/http/server.lua:108: in function 'process_next'
/usr/local/lib/prosody/net/http/server.lua:124: in function 'success_cb'
/usr/local/lib/prosody/net/http/parser.lua:177: in function 'feed'
/usr/local/lib/prosody/net/http/server.lua:155: in function </usr/local/lib/prosody/net/http/server.lua:154>
(...tail calls...)
/usr/local/lib/prosody/net/server_select.lua:915: in function </usr/local/lib/prosody/net/server_select.lua:899>
[C]: in function 'xpcall'
/usr/local/lib/prosody/../../bin/prosody:80: in function 'loop'
/usr/local/lib/prosody/../../bin/prosody:90: in main chunk
[C]: in ?
(a bit older release)
Actual code base: https://hg.prosody.im/trunk/file/tip/net/http/files.lua#l83
local etag = ('"%02x-%x-%x-%x"'):format(attr.dev or 0, attr.ino or 0, attr.size or 0, attr.modification or 0);
On FreeBSD stat.dev is uint64_t and looks like it is converted to int32_t somewhere in lua or prosody and result is negative.
Quick fix:
local etag = ('"%02x-%x-%x-%x"'):format(math.abs(attr.dev or 0), attr.ino or 0, attr.size or 0, attr.modification or 0);
produces ETag: "78ff00ff-12f9c-2b4548-5e6103f3"
Thanks for the report
That error only seems to exist in Lua 5.2. In Lua 5.1 and Lua 5.3 it happily produces something.
Does this mean a similar error would occur if the inode is over 31 bits large, or if the file is created past 2038?
Changes
tags Status-Accepted OpSys-FreeBSD
rim
on
Probably yes.
twm
on
The "stat" syscall in luafilesystem will return unsigned 64-bit integers for dev, inode, mtime, etc. on 64-bit platforms. However, Lua can't handle these correctly, as all numeric types are stored as signed 64-bit floats internally, resulting in wrong or even negative values in lfs.attributes. In theory this could happen very randomly on filesystems with 64-bit inodes.
As a workaround, rather than truncating lfs.attributes thus making the output even more unpredictable, Prosody could generate the etag from attributes that are unlikely to generate overflows, e.g. size and date (at least for now), possibly a hash of the filename.
Ultimately this needs to be fixed in luafilesystem, but this is unlikely to happen for Lua 5.1 and Lua 5.2. The behaviour of Lua 5.3 could be different as 5.3 has an internal integer type - I haven't tested this yet (currently running Prosody 0.11.5 on Lua 5.2).
rim
on
As easy way to fix it - etag can be removed. :)
Adding inode to etag - bad idea: inode can be changed but file content not, etag must not change in this case.
Probably better get ctime, mtime, size and hash it.
http.server error Traceback[httpserver]: /usr/local/lib/prosody/modules/mod_http_files.lua:115: bad argument #1 to 'format' (not a non-negative number in proper range) stack traceback: [C]: in function 'format' /usr/local/lib/prosody/modules/mod_http_files.lua:115: in function </usr/local/lib/prosody/modules/mod_http_files.lua:96> (...tail calls...) /usr/local/lib/prosody/util/events.lua:79: in function </usr/local/lib/prosody/util/events.lua:75> (...tail calls...) /usr/local/lib/prosody/net/http/server.lua:248: in function </usr/local/lib/prosody/net/http/server.lua:176> [C]: in function 'xpcall' /usr/local/lib/prosody/net/http/server.lua:108: in function 'process_next' /usr/local/lib/prosody/net/http/server.lua:124: in function 'success_cb' /usr/local/lib/prosody/net/http/parser.lua:177: in function 'feed' /usr/local/lib/prosody/net/http/server.lua:155: in function </usr/local/lib/prosody/net/http/server.lua:154> (...tail calls...) /usr/local/lib/prosody/net/server_select.lua:915: in function </usr/local/lib/prosody/net/server_select.lua:899> [C]: in function 'xpcall' /usr/local/lib/prosody/../../bin/prosody:80: in function 'loop' /usr/local/lib/prosody/../../bin/prosody:90: in main chunk [C]: in ? (a bit older release) Actual code base: https://hg.prosody.im/trunk/file/tip/net/http/files.lua#l83 local etag = ('"%02x-%x-%x-%x"'):format(attr.dev or 0, attr.ino or 0, attr.size or 0, attr.modification or 0); On FreeBSD stat.dev is uint64_t and looks like it is converted to int32_t somewhere in lua or prosody and result is negative. Quick fix: local etag = ('"%02x-%x-%x-%x"'):format(math.abs(attr.dev or 0), attr.ino or 0, attr.size or 0, attr.modification or 0); produces ETag: "78ff00ff-12f9c-2b4548-5e6103f3"
https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=244618
Thanks for the report That error only seems to exist in Lua 5.2. In Lua 5.1 and Lua 5.3 it happily produces something. Does this mean a similar error would occur if the inode is over 31 bits large, or if the file is created past 2038?
ChangesProbably yes.
The "stat" syscall in luafilesystem will return unsigned 64-bit integers for dev, inode, mtime, etc. on 64-bit platforms. However, Lua can't handle these correctly, as all numeric types are stored as signed 64-bit floats internally, resulting in wrong or even negative values in lfs.attributes. In theory this could happen very randomly on filesystems with 64-bit inodes. As a workaround, rather than truncating lfs.attributes thus making the output even more unpredictable, Prosody could generate the etag from attributes that are unlikely to generate overflows, e.g. size and date (at least for now), possibly a hash of the filename. Ultimately this needs to be fixed in luafilesystem, but this is unlikely to happen for Lua 5.1 and Lua 5.2. The behaviour of Lua 5.3 could be different as 5.3 has an internal integer type - I haven't tested this yet (currently running Prosody 0.11.5 on Lua 5.2).
As easy way to fix it - etag can be removed. :) Adding inode to etag - bad idea: inode can be changed but file content not, etag must not change in this case. Probably better get ctime, mtime, size and hash it.
Fixed in https://hg.prosody.im/0.11/rev/8f3b87eaec49
ChangesThanks!