diff options
author | Benoit Germain <bnt period germain arrobase gmail period com> | 2018-07-09 17:59:32 +0200 |
---|---|---|
committer | Benoit Germain <bnt period germain arrobase gmail period com> | 2018-07-09 17:59:32 +0200 |
commit | 1ec3f220f345f1c090a18adbaa90c0ead61e8ed3 (patch) | |
tree | c5b0380f59cf36c9b46049f6d79c9b05212aacba /src | |
parent | 95ca27b5658c9b4da4ec67f6e922ff370eae05e5 (diff) | |
download | lanes-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.c | 91 |
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 | ||
1483 | static 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); |