diff options
-rw-r--r-- | CHANGES | 4 | ||||
-rw-r--r-- | src/tools.c | 91 |
2 files changed, 59 insertions, 36 deletions
@@ -1,5 +1,9 @@ | |||
1 | CHANGES: | 1 | CHANGES: |
2 | 2 | ||
3 | CHANGE 124: BGe 9-Jul-18 | ||
4 | * Fix a stack overflow when copying large tables with verbose_errors option enabled | ||
5 | * Support for integer formatting in verbose errors | ||
6 | |||
3 | CHANGE 123: BGe 2-Aug-17 | 7 | CHANGE 123: BGe 2-Aug-17 |
4 | * added support for user-provided __gc in deep userdata | 8 | * added support for user-provided __gc in deep userdata |
5 | * more complete deep userdata sample | 9 | * more complete deep userdata sample |
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); |