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); |
