diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2024-06-21 14:55:12 -0300 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2024-06-21 14:55:12 -0300 |
commit | ec65ab878e04822f1cbcc3198f19076d57900e9f (patch) | |
tree | 936dd02a1e6c6eed833ccedaee2f7b1b3fc7e697 /lstrlib.c | |
parent | e24ce8c2b322226bbc211e57f301c265a2622c4b (diff) | |
download | lua-ec65ab878e04822f1cbcc3198f19076d57900e9f.tar.gz lua-ec65ab878e04822f1cbcc3198f19076d57900e9f.tar.bz2 lua-ec65ab878e04822f1cbcc3198f19076d57900e9f.zip |
Removed 'int' size limit for pack/unpack
Diffstat (limited to 'lstrlib.c')
-rw-r--r-- | lstrlib.c | 67 |
1 files changed, 38 insertions, 29 deletions
@@ -1447,14 +1447,14 @@ typedef enum KOption { | |||
1447 | */ | 1447 | */ |
1448 | static int digit (int c) { return '0' <= c && c <= '9'; } | 1448 | static int digit (int c) { return '0' <= c && c <= '9'; } |
1449 | 1449 | ||
1450 | static int getnum (const char **fmt, int df) { | 1450 | static size_t getnum (const char **fmt, size_t df) { |
1451 | if (!digit(**fmt)) /* no number? */ | 1451 | if (!digit(**fmt)) /* no number? */ |
1452 | return df; /* return default value */ | 1452 | return df; /* return default value */ |
1453 | else { | 1453 | else { |
1454 | int a = 0; | 1454 | size_t a = 0; |
1455 | do { | 1455 | do { |
1456 | a = a*10 + (*((*fmt)++) - '0'); | 1456 | a = a*10 + (*((*fmt)++) - '0'); |
1457 | } while (digit(**fmt) && a <= ((int)MAXSIZE - 9)/10); | 1457 | } while (digit(**fmt) && a <= (MAX_SIZE - 9)/10); |
1458 | return a; | 1458 | return a; |
1459 | } | 1459 | } |
1460 | } | 1460 | } |
@@ -1462,14 +1462,14 @@ static int getnum (const char **fmt, int df) { | |||
1462 | 1462 | ||
1463 | /* | 1463 | /* |
1464 | ** Read an integer numeral and raises an error if it is larger | 1464 | ** Read an integer numeral and raises an error if it is larger |
1465 | ** than the maximum size for integers. | 1465 | ** than the maximum size of integers. |
1466 | */ | 1466 | */ |
1467 | static int getnumlimit (Header *h, const char **fmt, int df) { | 1467 | static int getnumlimit (Header *h, const char **fmt, int df) { |
1468 | int sz = getnum(fmt, df); | 1468 | size_t sz = getnum(fmt, df); |
1469 | if (l_unlikely(sz > MAXINTSIZE || sz <= 0)) | 1469 | if (l_unlikely((sz - 1u) >= MAXINTSIZE)) |
1470 | return luaL_error(h->L, "integral size (%d) out of limits [1,%d]", | 1470 | return luaL_error(h->L, "integral size (%d) out of limits [1,%d]", |
1471 | sz, MAXINTSIZE); | 1471 | sz, MAXINTSIZE); |
1472 | return sz; | 1472 | return cast_int(sz); |
1473 | } | 1473 | } |
1474 | 1474 | ||
1475 | 1475 | ||
@@ -1486,7 +1486,7 @@ static void initheader (lua_State *L, Header *h) { | |||
1486 | /* | 1486 | /* |
1487 | ** Read and classify next option. 'size' is filled with option's size. | 1487 | ** Read and classify next option. 'size' is filled with option's size. |
1488 | */ | 1488 | */ |
1489 | static KOption getoption (Header *h, const char **fmt, int *size) { | 1489 | static KOption getoption (Header *h, const char **fmt, size_t *size) { |
1490 | /* dummy structure to get native alignment requirements */ | 1490 | /* dummy structure to get native alignment requirements */ |
1491 | struct cD { char c; union { LUAI_MAXALIGN; } u; }; | 1491 | struct cD { char c; union { LUAI_MAXALIGN; } u; }; |
1492 | int opt = *((*fmt)++); | 1492 | int opt = *((*fmt)++); |
@@ -1508,8 +1508,8 @@ static KOption getoption (Header *h, const char **fmt, int *size) { | |||
1508 | case 'I': *size = getnumlimit(h, fmt, sizeof(int)); return Kuint; | 1508 | case 'I': *size = getnumlimit(h, fmt, sizeof(int)); return Kuint; |
1509 | case 's': *size = getnumlimit(h, fmt, sizeof(size_t)); return Kstring; | 1509 | case 's': *size = getnumlimit(h, fmt, sizeof(size_t)); return Kstring; |
1510 | case 'c': | 1510 | case 'c': |
1511 | *size = getnum(fmt, -1); | 1511 | *size = getnum(fmt, cast_sizet(-1)); |
1512 | if (l_unlikely(*size == -1)) | 1512 | if (l_unlikely(*size == cast_sizet(-1))) |
1513 | luaL_error(h->L, "missing size for format option 'c'"); | 1513 | luaL_error(h->L, "missing size for format option 'c'"); |
1514 | return Kchar; | 1514 | return Kchar; |
1515 | case 'z': return Kzstr; | 1515 | case 'z': return Kzstr; |
@@ -1540,9 +1540,9 @@ static KOption getoption (Header *h, const char **fmt, int *size) { | |||
1540 | ** despite its size. | 1540 | ** despite its size. |
1541 | */ | 1541 | */ |
1542 | static KOption getdetails (Header *h, size_t totalsize, | 1542 | static KOption getdetails (Header *h, size_t totalsize, |
1543 | const char **fmt, int *psize, int *ntoalign) { | 1543 | const char **fmt, size_t *psize, int *ntoalign) { |
1544 | KOption opt = getoption(h, fmt, psize); | 1544 | KOption opt = getoption(h, fmt, psize); |
1545 | int align = *psize; /* usually, alignment follows size */ | 1545 | size_t align = *psize; /* usually, alignment follows size */ |
1546 | if (opt == Kpaddalign) { /* 'X' gets alignment from following option */ | 1546 | if (opt == Kpaddalign) { /* 'X' gets alignment from following option */ |
1547 | if (**fmt == '\0' || getoption(h, fmt, &align) == Kchar || align == 0) | 1547 | if (**fmt == '\0' || getoption(h, fmt, &align) == Kchar || align == 0) |
1548 | luaL_argerror(h->L, 1, "invalid next option for option 'X'"); | 1548 | luaL_argerror(h->L, 1, "invalid next option for option 'X'"); |
@@ -1550,9 +1550,9 @@ static KOption getdetails (Header *h, size_t totalsize, | |||
1550 | if (align <= 1 || opt == Kchar) /* need no alignment? */ | 1550 | if (align <= 1 || opt == Kchar) /* need no alignment? */ |
1551 | *ntoalign = 0; | 1551 | *ntoalign = 0; |
1552 | else { | 1552 | else { |
1553 | if (align > h->maxalign) /* enforce maximum alignment */ | 1553 | if (align > cast_sizet(h->maxalign)) /* enforce maximum alignment */ |
1554 | align = h->maxalign; | 1554 | align = h->maxalign; |
1555 | if (l_unlikely((align & (align - 1)) != 0)) /* not a power of 2? */ | 1555 | if (l_unlikely(!ispow2(align))) /* not a power of 2? */ |
1556 | luaL_argerror(h->L, 1, "format asks for alignment not power of 2"); | 1556 | luaL_argerror(h->L, 1, "format asks for alignment not power of 2"); |
1557 | *ntoalign = (align - (int)(totalsize & (align - 1))) & (align - 1); | 1557 | *ntoalign = (align - (int)(totalsize & (align - 1))) & (align - 1); |
1558 | } | 1558 | } |
@@ -1609,8 +1609,11 @@ static int str_pack (lua_State *L) { | |||
1609 | lua_pushnil(L); /* mark to separate arguments from string buffer */ | 1609 | lua_pushnil(L); /* mark to separate arguments from string buffer */ |
1610 | luaL_buffinit(L, &b); | 1610 | luaL_buffinit(L, &b); |
1611 | while (*fmt != '\0') { | 1611 | while (*fmt != '\0') { |
1612 | int size, ntoalign; | 1612 | int ntoalign; |
1613 | size_t size; | ||
1613 | KOption opt = getdetails(&h, totalsize, &fmt, &size, &ntoalign); | 1614 | KOption opt = getdetails(&h, totalsize, &fmt, &size, &ntoalign); |
1615 | luaL_argcheck(L, size + ntoalign <= MAX_SIZE - totalsize, arg, | ||
1616 | "result too long"); | ||
1614 | totalsize += ntoalign + size; | 1617 | totalsize += ntoalign + size; |
1615 | while (ntoalign-- > 0) | 1618 | while (ntoalign-- > 0) |
1616 | luaL_addchar(&b, LUAL_PACKPADBYTE); /* fill alignment */ | 1619 | luaL_addchar(&b, LUAL_PACKPADBYTE); /* fill alignment */ |
@@ -1660,18 +1663,21 @@ static int str_pack (lua_State *L) { | |||
1660 | case Kchar: { /* fixed-size string */ | 1663 | case Kchar: { /* fixed-size string */ |
1661 | size_t len; | 1664 | size_t len; |
1662 | const char *s = luaL_checklstring(L, arg, &len); | 1665 | const char *s = luaL_checklstring(L, arg, &len); |
1663 | luaL_argcheck(L, len <= (size_t)size, arg, | 1666 | luaL_argcheck(L, len <= size, arg, "string longer than given size"); |
1664 | "string longer than given size"); | ||
1665 | luaL_addlstring(&b, s, len); /* add string */ | 1667 | luaL_addlstring(&b, s, len); /* add string */ |
1666 | while (len++ < (size_t)size) /* pad extra space */ | 1668 | if (len < size) { /* does it need padding? */ |
1667 | luaL_addchar(&b, LUAL_PACKPADBYTE); | 1669 | size_t psize = size - len; /* pad size */ |
1670 | char *buff = luaL_prepbuffsize(&b, psize); | ||
1671 | memset(buff, LUAL_PACKPADBYTE, psize); | ||
1672 | luaL_addsize(&b, psize); | ||
1673 | } | ||
1668 | break; | 1674 | break; |
1669 | } | 1675 | } |
1670 | case Kstring: { /* strings with length count */ | 1676 | case Kstring: { /* strings with length count */ |
1671 | size_t len; | 1677 | size_t len; |
1672 | const char *s = luaL_checklstring(L, arg, &len); | 1678 | const char *s = luaL_checklstring(L, arg, &len); |
1673 | luaL_argcheck(L, size >= (int)sizeof(size_t) || | 1679 | luaL_argcheck(L, size >= sizeof(lua_Unsigned) || |
1674 | len < ((size_t)1 << (size * NB)), | 1680 | len < ((lua_Unsigned)1 << (size * NB)), |
1675 | arg, "string length does not fit in given size"); | 1681 | arg, "string length does not fit in given size"); |
1676 | packint(&b, (lua_Unsigned)len, h.islittle, size, 0); /* pack length */ | 1682 | packint(&b, (lua_Unsigned)len, h.islittle, size, 0); /* pack length */ |
1677 | luaL_addlstring(&b, s, len); | 1683 | luaL_addlstring(&b, s, len); |
@@ -1701,19 +1707,20 @@ static int str_pack (lua_State *L) { | |||
1701 | static int str_packsize (lua_State *L) { | 1707 | static int str_packsize (lua_State *L) { |
1702 | Header h; | 1708 | Header h; |
1703 | const char *fmt = luaL_checkstring(L, 1); /* format string */ | 1709 | const char *fmt = luaL_checkstring(L, 1); /* format string */ |
1704 | size_t totalsize = 0; /* accumulate total size of result */ | 1710 | lua_Integer totalsize = 0; /* accumulate total size of result */ |
1705 | initheader(L, &h); | 1711 | initheader(L, &h); |
1706 | while (*fmt != '\0') { | 1712 | while (*fmt != '\0') { |
1707 | int size, ntoalign; | 1713 | int ntoalign; |
1714 | size_t size; | ||
1708 | KOption opt = getdetails(&h, totalsize, &fmt, &size, &ntoalign); | 1715 | KOption opt = getdetails(&h, totalsize, &fmt, &size, &ntoalign); |
1709 | luaL_argcheck(L, opt != Kstring && opt != Kzstr, 1, | 1716 | luaL_argcheck(L, opt != Kstring && opt != Kzstr, 1, |
1710 | "variable-length format"); | 1717 | "variable-length format"); |
1711 | size += ntoalign; /* total space used by option */ | 1718 | size += ntoalign; /* total space used by option */ |
1712 | luaL_argcheck(L, totalsize <= MAXSIZE - size, 1, | 1719 | luaL_argcheck(L, totalsize <= LUA_MAXINTEGER - cast(lua_Integer, size), |
1713 | "format result too large"); | 1720 | 1, "format result too large"); |
1714 | totalsize += size; | 1721 | totalsize += size; |
1715 | } | 1722 | } |
1716 | lua_pushinteger(L, (lua_Integer)totalsize); | 1723 | lua_pushinteger(L, totalsize); |
1717 | return 1; | 1724 | return 1; |
1718 | } | 1725 | } |
1719 | 1726 | ||
@@ -1762,9 +1769,10 @@ static int str_unpack (lua_State *L) { | |||
1762 | luaL_argcheck(L, pos <= ld, 3, "initial position out of string"); | 1769 | luaL_argcheck(L, pos <= ld, 3, "initial position out of string"); |
1763 | initheader(L, &h); | 1770 | initheader(L, &h); |
1764 | while (*fmt != '\0') { | 1771 | while (*fmt != '\0') { |
1765 | int size, ntoalign; | 1772 | int ntoalign; |
1773 | size_t size; | ||
1766 | KOption opt = getdetails(&h, pos, &fmt, &size, &ntoalign); | 1774 | KOption opt = getdetails(&h, pos, &fmt, &size, &ntoalign); |
1767 | luaL_argcheck(L, (size_t)ntoalign + size <= ld - pos, 2, | 1775 | luaL_argcheck(L, ntoalign + size <= ld - pos, 2, |
1768 | "data string too short"); | 1776 | "data string too short"); |
1769 | pos += ntoalign; /* skip alignment */ | 1777 | pos += ntoalign; /* skip alignment */ |
1770 | /* stack space for item + next position */ | 1778 | /* stack space for item + next position */ |
@@ -1801,7 +1809,8 @@ static int str_unpack (lua_State *L) { | |||
1801 | break; | 1809 | break; |
1802 | } | 1810 | } |
1803 | case Kstring: { | 1811 | case Kstring: { |
1804 | size_t len = (size_t)unpackint(L, data + pos, h.islittle, size, 0); | 1812 | lua_Unsigned len = (lua_Unsigned)unpackint(L, data + pos, |
1813 | h.islittle, size, 0); | ||
1805 | luaL_argcheck(L, len <= ld - pos - size, 2, "data string too short"); | 1814 | luaL_argcheck(L, len <= ld - pos - size, 2, "data string too short"); |
1806 | lua_pushlstring(L, data + pos + size, len); | 1815 | lua_pushlstring(L, data + pos + size, len); |
1807 | pos += len; /* skip string */ | 1816 | pos += len; /* skip string */ |