diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2014-04-10 16:45:43 -0300 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2014-04-10 16:45:43 -0300 |
commit | 115fa770091881d27bf265c61078dd80f17fd1a0 (patch) | |
tree | 081185f79ccaadfac21b1c60b436d0d3c83498ef | |
parent | 561030c211a8de6b46554fca4df13925b38a4758 (diff) | |
download | lua-115fa770091881d27bf265c61078dd80f17fd1a0.tar.gz lua-115fa770091881d27bf265c61078dd80f17fd1a0.tar.bz2 lua-115fa770091881d27bf265c61078dd80f17fd1a0.zip |
maximum size for dump of integers is size of lua_Integer (which
means that there is no overflows when undumping)
-rw-r--r-- | lstrlib.c | 53 |
1 files changed, 17 insertions, 36 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lstrlib.c,v 1.192 2014/04/03 13:29:24 roberto Exp roberto $ | 2 | ** $Id: lstrlib.c,v 1.193 2014/04/10 18:24:12 roberto Exp roberto $ |
3 | ** Standard library for string operations and pattern-matching | 3 | ** Standard library for string operations and pattern-matching |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -946,9 +946,6 @@ static int str_format (lua_State *L) { | |||
946 | ** ======================================================= | 946 | ** ======================================================= |
947 | */ | 947 | */ |
948 | 948 | ||
949 | /* maximum size for the binary representation of an integer */ | ||
950 | #define MAXINTSIZE 8 | ||
951 | |||
952 | 949 | ||
953 | /* number of bits in a character */ | 950 | /* number of bits in a character */ |
954 | #define NB CHAR_BIT | 951 | #define NB CHAR_BIT |
@@ -959,9 +956,12 @@ static int str_format (lua_State *L) { | |||
959 | /* mask for one character without sign ((NB - 1) ones) */ | 956 | /* mask for one character without sign ((NB - 1) ones) */ |
960 | #define SM ((1 << (NB - 1)) - 1) | 957 | #define SM ((1 << (NB - 1)) - 1) |
961 | 958 | ||
962 | 959 | /* size of a lua_Integer */ | |
963 | #define SZINT ((int)sizeof(lua_Integer)) | 960 | #define SZINT ((int)sizeof(lua_Integer)) |
964 | 961 | ||
962 | /* maximum size for the binary representation of an integer */ | ||
963 | #define MAXINTSIZE SZINT | ||
964 | |||
965 | 965 | ||
966 | static union { | 966 | static union { |
967 | int dummy; | 967 | int dummy; |
@@ -989,7 +989,7 @@ static int getintsize (lua_State *L, int arg) { | |||
989 | } | 989 | } |
990 | 990 | ||
991 | 991 | ||
992 | static int dumpint (char *buff, lua_Integer n, int littleendian, int size) { | 992 | static int dumpint (char *buff, lua_Unsigned n, int littleendian, int size) { |
993 | int i; | 993 | int i; |
994 | if (littleendian) { | 994 | if (littleendian) { |
995 | for (i = 0; i < size - 1; i++) { | 995 | for (i = 0; i < size - 1; i++) { |
@@ -1004,10 +1004,13 @@ static int dumpint (char *buff, lua_Integer n, int littleendian, int size) { | |||
1004 | } | 1004 | } |
1005 | } | 1005 | } |
1006 | buff[i] = (n & MC); /* last byte */ | 1006 | buff[i] = (n & MC); /* last byte */ |
1007 | /* test for overflow: OK if there are only zeros left in higher bytes, | 1007 | if (size < SZINT) { /* need test for overflow? */ |
1008 | or if there are only ones left and dumped number is negative (signal | 1008 | /* OK if there are only zeros left in higher bytes, |
1009 | bit, the higher bit in last byte, is one) */ | 1009 | or only ones left (excluding non-signal bits in last byte) */ |
1010 | return ((n & ~(lua_Integer)MC) == 0 || (n | SM) == ~(lua_Integer)0); | 1010 | return ((n & ~(lua_Integer)MC) == 0 || |
1011 | (n | SM) == (~(lua_Unsigned)0 >> ((size - 1) * NB))); | ||
1012 | } | ||
1013 | else return 1; /* no overflow can occur with full size */ | ||
1011 | } | 1014 | } |
1012 | 1015 | ||
1013 | 1016 | ||
@@ -1016,7 +1019,7 @@ static int dumpint_l (lua_State *L) { | |||
1016 | lua_Integer n = luaL_checkinteger(L, 1); | 1019 | lua_Integer n = luaL_checkinteger(L, 1); |
1017 | int size = getintsize(L, 2); | 1020 | int size = getintsize(L, 2); |
1018 | int endian = getendian(L, 3); | 1021 | int endian = getendian(L, 3); |
1019 | if (dumpint(buff, n, endian, size)) | 1022 | if (dumpint(buff, (lua_Unsigned)n, endian, size)) |
1020 | lua_pushlstring(L, buff, size); | 1023 | lua_pushlstring(L, buff, size); |
1021 | else | 1024 | else |
1022 | luaL_error(L, "integer does not fit into given size (%d)", size); | 1025 | luaL_error(L, "integer does not fit into given size (%d)", size); |
@@ -1024,27 +1027,10 @@ static int dumpint_l (lua_State *L) { | |||
1024 | } | 1027 | } |
1025 | 1028 | ||
1026 | 1029 | ||
1027 | /* mask to check higher-order byte in a Lua integer */ | 1030 | static lua_Integer undumpint (const char *buff, int littleendian, int size) { |
1028 | #define HIGHERBYTE ((lua_Unsigned)MC << (NB * (SZINT - 1))) | ||
1029 | |||
1030 | /* mask to check higher-order byte + signal bit of next (lower) byte */ | ||
1031 | #define HIGHERBYTE1 (HIGHERBYTE | (HIGHERBYTE >> 1)) | ||
1032 | |||
1033 | static int undumpint (const char *buff, lua_Integer *res, | ||
1034 | int littleendian, int size) { | ||
1035 | lua_Integer n = 0; | 1031 | lua_Integer n = 0; |
1036 | int i; | 1032 | int i; |
1037 | for (i = 0; i < size; i++) { | 1033 | for (i = 0; i < size; i++) { |
1038 | if (i >= SZINT) { /* will throw away a byte? */ | ||
1039 | /* check for overflow: it is OK to throw away leading zeros for a | ||
1040 | positive number, leading ones for a negative number, and a | ||
1041 | leading zero byte to allow unsigned integers with a 1 in | ||
1042 | its "signal bit" */ | ||
1043 | if (!((n & HIGHERBYTE1) == 0 || /* zeros for positive number */ | ||
1044 | (n & HIGHERBYTE1) == HIGHERBYTE1 || /* ones for negative number */ | ||
1045 | ((n & HIGHERBYTE) == 0 && i == size - 1))) /* leading zero */ | ||
1046 | return 0; /* overflow */ | ||
1047 | } | ||
1048 | n <<= NB; | 1034 | n <<= NB; |
1049 | n |= (lua_Integer)(unsigned char)buff[littleendian ? size - 1 - i : i]; | 1035 | n |= (lua_Integer)(unsigned char)buff[littleendian ? size - 1 - i : i]; |
1050 | } | 1036 | } |
@@ -1052,13 +1038,11 @@ static int undumpint (const char *buff, lua_Integer *res, | |||
1052 | lua_Unsigned mask = (lua_Unsigned)1 << (size*NB - 1); | 1038 | lua_Unsigned mask = (lua_Unsigned)1 << (size*NB - 1); |
1053 | n = (lua_Integer)((n ^ mask) - mask); /* do sign extension */ | 1039 | n = (lua_Integer)((n ^ mask) - mask); /* do sign extension */ |
1054 | } | 1040 | } |
1055 | *res = n; | 1041 | return n; |
1056 | return 1; | ||
1057 | } | 1042 | } |
1058 | 1043 | ||
1059 | 1044 | ||
1060 | static int undumpint_l (lua_State *L) { | 1045 | static int undumpint_l (lua_State *L) { |
1061 | lua_Integer res; | ||
1062 | size_t len; | 1046 | size_t len; |
1063 | const char *s = luaL_checklstring(L, 1, &len); | 1047 | const char *s = luaL_checklstring(L, 1, &len); |
1064 | lua_Integer pos = posrelat(luaL_optinteger(L, 2, 1), len); | 1048 | lua_Integer pos = posrelat(luaL_optinteger(L, 2, 1), len); |
@@ -1066,10 +1050,7 @@ static int undumpint_l (lua_State *L) { | |||
1066 | int endian = getendian(L, 4); | 1050 | int endian = getendian(L, 4); |
1067 | luaL_argcheck(L, 1 <= pos && (size_t)pos + size - 1 <= len, 1, | 1051 | luaL_argcheck(L, 1 <= pos && (size_t)pos + size - 1 <= len, 1, |
1068 | "string too short"); | 1052 | "string too short"); |
1069 | if(undumpint(s + pos - 1, &res, endian, size)) | 1053 | lua_pushinteger(L, undumpint(s + pos - 1, endian, size)); |
1070 | lua_pushinteger(L, res); | ||
1071 | else | ||
1072 | luaL_error(L, "result does not fit into a Lua integer"); | ||
1073 | return 1; | 1054 | return 1; |
1074 | } | 1055 | } |
1075 | 1056 | ||