aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorBenoit Germain <bnt period germain arrobase gmail period com>2018-07-09 17:59:32 +0200
committerBenoit Germain <bnt period germain arrobase gmail period com>2018-07-09 17:59:32 +0200
commit1ec3f220f345f1c090a18adbaa90c0ead61e8ed3 (patch)
treec5b0380f59cf36c9b46049f6d79c9b05212aacba /src
parent95ca27b5658c9b4da4ec67f6e922ff370eae05e5 (diff)
downloadlanes-1ec3f220f345f1c090a18adbaa90c0ead61e8ed3.tar.gz
lanes-1ec3f220f345f1c090a18adbaa90c0ead61e8ed3.tar.bz2
lanes-1ec3f220f345f1c090a18adbaa90c0ead61e8ed3.zip
verbose_error improvements
* Fix a stack overflow when copying large tables with verbose_errors option enabled * Support for integer formatting in verbose errors
Diffstat (limited to 'src')
-rw-r--r--src/tools.c91
1 files changed, 55 insertions, 36 deletions
diff --git a/src/tools.c b/src/tools.c
index 9403fd6..59037e6 100644
--- a/src/tools.c
+++ b/src/tools.c
@@ -1480,6 +1480,58 @@ static void push_cached_func( struct s_Universe* U, lua_State* L2, uint_t L2_cac
1480 } 1480 }
1481} 1481}
1482 1482
1483static void inter_copy_keyvaluepair( struct s_Universe* U, lua_State* L2, uint_t L2_cache_i, lua_State* L, enum e_vt vt, enum eLookupMode mode_, char const* upName_)
1484{
1485 uint_t val_i = lua_gettop( L);
1486 uint_t key_i = val_i - 1;
1487
1488 // Only basic key types are copied over; others ignored
1489 if( inter_copy_one_( U, L2, 0 /*key*/, L, key_i, VT_KEY, mode_, upName_))
1490 {
1491 char* valPath = (char*) upName_;
1492 if( U->verboseErrors)
1493 {
1494 // for debug purposes, let's try to build a useful name
1495 if( lua_type( L, key_i) == LUA_TSTRING)
1496 {
1497 char const* key = lua_tostring( L, key_i);
1498 size_t const keyRawLen = lua_rawlen( L, key_i);
1499 size_t const bufLen = strlen( upName_) + keyRawLen + 2;
1500 valPath = (char*) alloca( bufLen);
1501 sprintf( valPath, "%s.%*s", upName_, (int) keyRawLen, key);
1502 key = NULL;
1503 }
1504#if defined LUA_LNUM || LUA_VERSION_NUM >= 503
1505 else if( lua_isinteger( L, key_i))
1506 {
1507 lua_Integer key = lua_tointeger( L, key_i);
1508 valPath = (char*) alloca( strlen( upName_) + 32 + 3);
1509 sprintf( valPath, "%s[" LUA_INTEGER_FMT "]", upName_, key);
1510 }
1511#endif // defined LUA_LNUM || LUA_VERSION_NUM >= 503
1512 else if( lua_type( L, key_i) == LUA_TNUMBER)
1513 {
1514 lua_Number key = lua_tonumber( L, key_i);
1515 valPath = (char*) alloca( strlen( upName_) + 32 + 3);
1516 sprintf( valPath, "%s[" LUA_NUMBER_FMT "]", upName_, key);
1517 }
1518 }
1519 /*
1520 * Contents of metatables are copied with cache checking;
1521 * important to detect loops.
1522 */
1523 if( inter_copy_one_( U, L2, L2_cache_i, L, val_i, VT_NORMAL, mode_, valPath))
1524 {
1525 ASSERT_L( lua_istable( L2, -3));
1526 lua_rawset( L2, -3); // add to table (pops key & val)
1527 }
1528 else
1529 {
1530 luaL_error( L, "Unable to copy over type '%s' (in %s)", luaL_typename( L, val_i), (vt == VT_NORMAL) ? "table" : "metatable");
1531 }
1532 }
1533}
1534
1483/* 1535/*
1484* Copies a value from 'L' state (at index 'i') to 'L2' state. Does not remove 1536* Copies a value from 'L' state (at index 'i') to 'L2' state. Does not remove
1485* the original value. 1537* the original value.
@@ -1529,7 +1581,7 @@ static bool_t inter_copy_one_( struct s_Universe* U, lua_State* L2, uint_t L2_ca
1529 break; 1581 break;
1530 } 1582 }
1531 else 1583 else
1532#endif 1584#endif // defined LUA_LNUM || LUA_VERSION_NUM >= 503
1533 { 1585 {
1534 lua_Number v = lua_tonumber( L, i); 1586 lua_Number v = lua_tonumber( L, i);
1535 DEBUGSPEW_CODE( if( vt == VT_KEY) fprintf( stderr, INDENT_BEGIN "KEY: " LUA_NUMBER_FMT "\n" INDENT_END, v)); 1587 DEBUGSPEW_CODE( if( vt == VT_KEY) fprintf( stderr, INDENT_BEGIN "KEY: " LUA_NUMBER_FMT "\n" INDENT_END, v));
@@ -1655,41 +1707,8 @@ static bool_t inter_copy_one_( struct s_Universe* U, lua_State* L2, uint_t L2_ca
1655 lua_pushnil( L); // start iteration 1707 lua_pushnil( L); // start iteration
1656 while( lua_next( L, i)) 1708 while( lua_next( L, i))
1657 { 1709 {
1658 uint_t val_i = lua_gettop( L); 1710 // need a function to prevent overflowing the stack with verboseErrors-induced alloca()
1659 uint_t key_i = val_i - 1; 1711 inter_copy_keyvaluepair( U, L2, L2_cache_i, L, vt, mode_, upName_);
1660
1661 // Only basic key types are copied over; others ignored
1662 if( inter_copy_one_( U, L2, 0 /*key*/, L, key_i, VT_KEY, mode_, upName_))
1663 {
1664 char* valPath = (char*) upName_;
1665 if( U->verboseErrors)
1666 {
1667 // for debug purposes, let's try to build a useful name
1668 if( lua_type( L, key_i) == LUA_TSTRING)
1669 {
1670 valPath = (char*) alloca( strlen( upName_) + strlen( lua_tostring( L, key_i)) + 2);
1671 sprintf( valPath, "%s.%s", upName_, lua_tostring( L, key_i));
1672 }
1673 else if( lua_type( L, key_i) == LUA_TNUMBER)
1674 {
1675 valPath = (char*) alloca( strlen( upName_) + 32 + 3);
1676 sprintf( valPath, "%s[" LUA_NUMBER_FMT "]", upName_, lua_tonumber( L, key_i));
1677 }
1678 }
1679 /*
1680 * Contents of metatables are copied with cache checking;
1681 * important to detect loops.
1682 */
1683 if( inter_copy_one_( U, L2, L2_cache_i, L, val_i, VT_NORMAL, mode_, valPath))
1684 {
1685 ASSERT_L( lua_istable( L2, -3));
1686 lua_rawset( L2, -3); // add to table (pops key & val)
1687 }
1688 else
1689 {
1690 luaL_error( L, "Unable to copy over type '%s' (in %s)", luaL_typename( L, val_i), (vt == VT_NORMAL) ? "table" : "metatable");
1691 }
1692 }
1693 lua_pop( L, 1); // pop value (next round) 1712 lua_pop( L, 1); // pop value (next round)
1694 } 1713 }
1695 STACK_MID( L, 0); 1714 STACK_MID( L, 0);