`string.unpack` 's bug in option `z`

classic Classic list List threaded Threaded
10 messages Options
Reply | Threaded
Open this post in threaded view
|

`string.unpack` 's bug in option `z`

actboy168@gmail.com

 

Lua 5.3.5  Copyright (C) 1994-2018 Lua.org, PUC-Rio

> print(string.unpack('z', 'ABC'))

ABC     5

> 

 

This is not a zero-terminated string, so I think lua should raise an error.

 

--actboy168

 

Reply | Threaded
Open this post in threaded view
|

Re: `string.unpack` 's bug in option `z`

Dirk Laurie-2
Op Ma., 3 Sep. 2018 om 04:29 het actboy168 <[hidden email]> geskryf:

> Lua 5.3.5  Copyright (C) 1994-2018 Lua.org, PUC-Rio
>
> > print(string.unpack('z', 'ABC'))
> ABC     5
> This is not a zero-terminated string, so I think lua should raise an error.

You are right that 'ABC' is not a zero-terminated string, but I do not
agree that Lua should raise an error. The manual says 'All integral
options check overflows; ... string.unpack checks whether the read
value fits in a Lua integer.' There is no risk of overflow here, so an
error should not be raised, and the manual almost says so: 'Options
"c" and "z" are not aligned'.

The string pack/unpack routines are taken from Roberto's 'struct'
library http://www.inf.puc-rio.br/~roberto/struct/, which has been in
existence for at least six years (timestamp on the makefile).

BTW that library is a beautiful example of how to write C API code
that compiles on all Lua versions from 5.0 to 5.4 with only this
version-dependent test:

#if (LUA_VERSION_NUM >= 502)
#define luaL_register(L,n,f)    luaL_newlib(L,f)
#endif

Reply | Threaded
Open this post in threaded view
|

Re: `string.unpack` 's bug in option `z`

actboy168@gmail.com

But the struct library will raise an error.

 

 

--actboy168

 

发件人: [hidden email]
发送时间: 201893 17:52
收件人: [hidden email]
主题: Re: `string.unpack` 's bug in option `z`

 

Op Ma., 3 Sep. 2018 om 04:29 het actboy168 <[hidden email]> geskryf:

 

> Lua 5.3.5  Copyright (C) 1994-2018 Lua.org, PUC-Rio

> 

> > print(string.unpack('z', 'ABC'))

> ABC     5

> This is not a zero-terminated string, so I think lua should raise an error.

 

You are right that 'ABC' is not a zero-terminated string, but I do not

agree that Lua should raise an error. The manual says 'All integral

options check overflows; ... string.unpack checks whether the read

value fits in a Lua integer.' There is no risk of overflow here, so an

error should not be raised, and the manual almost says so: 'Options

"c" and "z" are not aligned'.

 

The string pack/unpack routines are taken from Roberto's 'struct'

library http://www.inf.puc-rio.br/~roberto/struct/, which has been in

existence for at least six years (timestamp on the makefile).

 

BTW that library is a beautiful example of how to write C API code

that compiles on all Lua versions from 5.0 to 5.4 with only this

version-dependent test:

 

#if (LUA_VERSION_NUM >= 502)

#define luaL_register(L,n,f)    luaL_newlib(L,f)

#endif

 

 

Reply | Threaded
Open this post in threaded view
|

Re: `string.unpack` 's bug in option `z`

Dirk Laurie-2
Op Ma., 3 Sep. 2018 om 12:08 het actboy168 <[hidden email]> geskryf:
>
> But the struct library will raise an error.

True, but that error is:
   bad argument #1 to 'unpack' (invalid format option 'z')
I.e. the option 'z' is an addition available in the Lua 5.3 library version.

> 发件人: Dirk Laurie
> 发送时间: 2018年9月3日 17:52
> 收件人: Lua mailing list
> 主题: Re: `string.unpack` 's bug in option `z`
>
>
>
> Op Ma., 3 Sep. 2018 om 04:29 het actboy168 <[hidden email]> geskryf:
>
>
>
> > Lua 5.3.5  Copyright (C) 1994-2018 Lua.org, PUC-Rio
>
> >
>
> > > print(string.unpack('z', 'ABC'))
>
> > ABC     5
>
> > This is not a zero-terminated string, so I think lua should raise an error.
>
>
>
> You are right that 'ABC' is not a zero-terminated string, but I do not
>
> agree that Lua should raise an error. The manual says 'All integral
>
> options check overflows; ... string.unpack checks whether the read
>
> value fits in a Lua integer.' There is no risk of overflow here, so an
>
> error should not be raised, and the manual almost says so: 'Options
>
> "c" and "z" are not aligned'.
>
>
>
> The string pack/unpack routines are taken from Roberto's 'struct'
>
> library http://www.inf.puc-rio.br/~roberto/struct/, which has been in
>
> existence for at least six years (timestamp on the makefile).
>
>
>
> BTW that library is a beautiful example of how to write C API code
>
> that compiles on all Lua versions from 5.0 to 5.4 with only this
>
> version-dependent test:
>
>
>
> #if (LUA_VERSION_NUM >= 502)
>
> #define luaL_register(L,n,f)    luaL_newlib(L,f)
>
> #endif
>
>
>
>

Reply | Threaded
Open this post in threaded view
|

Re: `string.unpack` 's bug in option `z`

actboy168@gmail.com
In struct  library , option `s` means read a zero-terminated string.So the same test is
local struct = require 'struct'
print(struct .unpack('s', 'ABC'))

Dirk Laurie <[hidden email]> 于2018年9月3日周一 下午6:23写道:
Op Ma., 3 Sep. 2018 om 12:08 het actboy168 <[hidden email]> geskryf:
>
> But the struct library will raise an error.

True, but that error is:
   bad argument #1 to 'unpack' (invalid format option 'z')
I.e. the option 'z' is an addition available in the Lua 5.3 library version.



-- actboy168
Reply | Threaded
Open this post in threaded view
|

Re: `string.unpack` 's bug in option `z`

Daurnimator
In reply to this post by Dirk Laurie-2
On 3 September 2018 at 02:51, Dirk Laurie <[hidden email]> wrote:
> BTW that library is a beautiful example of how to write C API code
> that compiles on all Lua versions from 5.0 to 5.4 with only this
> version-dependent test:
>
> #if (LUA_VERSION_NUM >= 502)
> #define luaL_register(L,n,f)    luaL_newlib(L,f)
> #endif


I object: people should be writing against the newest lua version
available at the time, and using the preprocessor to gain *backwards*
compatibility.
Defining *older* functions in terms of new ones (forwards
compatibility) is in my opinion, an antipattern used for quicker
porting.

Reply | Threaded
Open this post in threaded view
|

Re: `string.unpack` 's bug in option `z`

Luiz Henrique de Figueiredo
> I object: people should be writing against the newest lua version
> available at the time, and using the preprocessor to gain *backwards*
> compatibility.

That's what I've done in the newer versions of my libraries, which now
work for Lua 5.x. I #include mycompat.h, which contains code like this:

#if LUA_VERSION_NUM <= 501

#define luaL_setmetatable(L,t) \
        luaL_getmetatable(L,t); \
        lua_setmetatable(L,-2)

#define luaL_setfuncs(L,r,n) \
        luaL_register(L,NULL,r)

#endif

For a more general solution, see
https://github.com/keplerproject/lua-compat-5.3

Reply | Threaded
Open this post in threaded view
|

Re: `string.unpack` 's bug in option `z`

Dirk Laurie-2
In reply to this post by actboy168@gmail.com
Op Ma., 3 Sep. 2018 om 13:41 het actboy168 <[hidden email]> geskryf:
>
> In struct  library , option `s` means read a zero-terminated string.So the same test is
> local struct = require 'struct'
> print(struct .unpack('s', 'ABC'))

Exactly. If you want the error message, use 's', not 'z'.

> string.unpack('s', 'ABC')
stdin:1: bad argument #2 to 'unpack' (data string too short)
stack traceback:
    [C]: in function 'string.unpack'
    stdin:1: in main chunk
    [C]: in ?



> Dirk Laurie <[hidden email]> 于2018年9月3日周一 下午6:23写道:
>>
>> Op Ma., 3 Sep. 2018 om 12:08 het actboy168 <[hidden email]> geskryf:
>> >
>> > But the struct library will raise an error.
>>
>> True, but that error is:
>>    bad argument #1 to 'unpack' (invalid format option 'z')
>> I.e. the option 'z' is an addition available in the Lua 5.3 library version.
>>
>
>
> -- actboy168

Reply | Threaded
Open this post in threaded view
|

Re: `string.unpack` 's bug in option `z`

Roberto Ierusalimschy
In reply to this post by actboy168@gmail.com

> Lua 5.3.5  Copyright (C) 1994-2018 Lua.org, PUC-Rio
> > print(string.unpack('z', 'ABC'))
> ABC     5
> >
>
> This is not a zero-terminated string, so I think lua should raise an error.

This has already been fixed in 5.4.

-- Roberto

Reply | Threaded
Open this post in threaded view
|

Re: `string.unpack` 's bug in option `z`

Sean Conner
In reply to this post by Daurnimator
It was thus said that the Great Daurnimator once stated:

> On 3 September 2018 at 02:51, Dirk Laurie <[hidden email]> wrote:
> > BTW that library is a beautiful example of how to write C API code
> > that compiles on all Lua versions from 5.0 to 5.4 with only this
> > version-dependent test:
> >
> > #if (LUA_VERSION_NUM >= 502)
> > #define luaL_register(L,n,f)    luaL_newlib(L,f)
> > #endif
>
>
> I object: people should be writing against the newest lua version
> available at the time, and using the preprocessor to gain *backwards*
> compatibility.
> Defining *older* functions in terms of new ones (forwards
> compatibility) is in my opinion, an antipattern used for quicker
> porting.

  But there's still an issue.  Take the following hypthetical Lua 5.1 code:

        static luaL_Reg const m_foo_reg[] = { /* ... */ };

        int luaopen_foo(lua_State *L)
        {
          luaL_register(L,"foo",m_foo_reg);
          return 1;
        }

The semantics of Lua 5.1 include the creation of the global "foo".  If I go
ahead and do this:

        #if LUA_VERSION_NUM == 501
        #  define luaL_newlib(state,reg) luaL_register((state),NULL,(reg))
        #endif

        static luaL_Reg const m_foo_reg[] = { /* ... */ };

        int luaopen_foo(lua_State *L)
        {
          luaL_newlib(L,m_foo_reg);
          return 1;
        }

This can *break* code on Lua 5.1---the global "foo" is not created. Yes, I
could get around this [1]:

        #if (LUA_VERSION_NUM == 501)
        #  define luaL_newlib(state,reg) luaL_register((state),"foo",(reg))
        #endif

but I'm not happy with that solution for this particular case.  What I
normally do is:

        static luaL_Reg const m_foo_reg[] = { /* ... */ };

        int luaopen_foo(lua_State *L)
        {
        # if LUA_VERSION_NUM == 501
          luaL_register(L,"foo",m_foo_reg);
        #else
          luaL_newlib(L,m_foo_reg);
        #endif
          return 1;
        }

which I'm not happy with either, but I think is "better" in that the name of
the module is closer to it's use than buried in a #define elsewhere.  Yes, I
could do the #define closer to this point, but that breaks my own coding
style.

  Another problematic pair of functions is lua_objlen() (Lua 5.1) and
luaL_len() (Lua 5.2+).  luaL_len() is *not* a direct replacement for
lua_objlen(), because one raises an error and one doesn't.

  -spc

[1] As I did here:
        https://github.com/spc476/lua-conmanorg/blob/380c78b15d0211f794be5ff94daefc0fed30e333/src/tls.c#L48