aboutsummaryrefslogtreecommitdiff
path: root/lstrlib.c
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2024-06-21 14:55:12 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2024-06-21 14:55:12 -0300
commitec65ab878e04822f1cbcc3198f19076d57900e9f (patch)
tree936dd02a1e6c6eed833ccedaee2f7b1b3fc7e697 /lstrlib.c
parente24ce8c2b322226bbc211e57f301c265a2622c4b (diff)
downloadlua-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.c67
1 files changed, 38 insertions, 29 deletions
diff --git a/lstrlib.c b/lstrlib.c
index ab33bffe..eb38b67d 100644
--- a/lstrlib.c
+++ b/lstrlib.c
@@ -1447,14 +1447,14 @@ typedef enum KOption {
1447*/ 1447*/
1448static int digit (int c) { return '0' <= c && c <= '9'; } 1448static int digit (int c) { return '0' <= c && c <= '9'; }
1449 1449
1450static int getnum (const char **fmt, int df) { 1450static 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*/
1467static int getnumlimit (Header *h, const char **fmt, int df) { 1467static 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*/
1489static KOption getoption (Header *h, const char **fmt, int *size) { 1489static 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*/
1542static KOption getdetails (Header *h, size_t totalsize, 1542static 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) {
1701static int str_packsize (lua_State *L) { 1707static 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 */