Index: trunk/php/luasandbox/php_luasandbox.h |
— | — | @@ -66,6 +66,7 @@ |
67 | 67 | struct timespec cpu_normal_limit; |
68 | 68 | struct timespec cpu_emergency_limit; |
69 | 69 | int function_index; |
| 70 | + unsigned int random_seed; |
70 | 71 | }; |
71 | 72 | typedef struct _php_luasandbox_obj php_luasandbox_obj; |
72 | 73 | |
Index: trunk/php/luasandbox/luasandbox.c |
— | — | @@ -10,6 +10,7 @@ |
11 | 11 | #include <float.h> |
12 | 12 | #include <signal.h> |
13 | 13 | #include <time.h> |
| 14 | +#include <stdlib.h> |
14 | 15 | |
15 | 16 | #include "php.h" |
16 | 17 | #include "php_ini.h" |
— | — | @@ -64,6 +65,8 @@ |
65 | 66 | static int luasandbox_call_php(lua_State * L); |
66 | 67 | static int luasandbox_dump_writer(lua_State * L, const void * p, size_t sz, void * ud); |
67 | 68 | static int luasandbox_base_tostring(lua_State * L); |
| 69 | +static int luasandbox_math_random(lua_State * L); |
| 70 | +static int luasandbox_math_randomseed(lua_State * L); |
68 | 71 | |
69 | 72 | char luasandbox_timeout_message[] = "The maximum execution time for this script was exceeded"; |
70 | 73 | |
— | — | @@ -425,6 +428,15 @@ |
426 | 429 | lua_setfield(L, -2, "dump"); |
427 | 430 | lua_pop(L, 1); |
428 | 431 | |
| 432 | + // Install our own versions of math.random and math.randomseed |
| 433 | + lua_getglobal(L, "math"); |
| 434 | + lua_pushcfunction(L, luasandbox_math_random); |
| 435 | + lua_setfield(L, -2, "random"); |
| 436 | + lua_pushcfunction(L, luasandbox_math_randomseed); |
| 437 | + lua_setfield(L, -2, "randomseed"); |
| 438 | + lua_pop(L, 1); |
| 439 | + |
| 440 | + |
429 | 441 | // Create a table for storing chunks |
430 | 442 | lua_newtable(L); |
431 | 443 | lua_setfield(L, LUA_REGISTRYINDEX, "php_luasandbox_chunks"); |
— | — | @@ -1736,6 +1748,54 @@ |
1737 | 1749 | return 1; |
1738 | 1750 | } |
1739 | 1751 | /* }}} */ |
| 1752 | + |
| 1753 | +/** {{{ luasandbox_math_random |
| 1754 | + * |
| 1755 | + * A math.random implementation that doesn't share state with PHP's rand() |
| 1756 | + */ |
| 1757 | +static int luasandbox_math_random(lua_State * L) |
| 1758 | +{ |
| 1759 | + php_luasandbox_obj * sandbox = luasandbox_get_php_obj(L); |
| 1760 | + |
| 1761 | + int i = rand_r(&sandbox->random_seed); |
| 1762 | + if (i >= RAND_MAX) { |
| 1763 | + i -= RAND_MAX; |
| 1764 | + } |
| 1765 | + lua_Number r = (lua_Number)i / (lua_Number)RAND_MAX; |
| 1766 | + switch (lua_gettop(L)) { /* check number of arguments */ |
| 1767 | + case 0: { /* no arguments */ |
| 1768 | + lua_pushnumber(L, r); /* Number between 0 and 1 */ |
| 1769 | + break; |
| 1770 | + } |
| 1771 | + case 1: { /* only upper limit */ |
| 1772 | + int u = luaL_checkint(L, 1); |
| 1773 | + luaL_argcheck(L, 1<=u, 1, "interval is empty"); |
| 1774 | + lua_pushnumber(L, floor(r*u)+1); /* int between 1 and `u' */ |
| 1775 | + break; |
| 1776 | + } |
| 1777 | + case 2: { /* lower and upper limits */ |
| 1778 | + int l = luaL_checkint(L, 1); |
| 1779 | + int u = luaL_checkint(L, 2); |
| 1780 | + luaL_argcheck(L, l<=u, 2, "interval is empty"); |
| 1781 | + lua_pushnumber(L, floor(r*(u-l+1))+l); /* int between `l' and `u' */ |
| 1782 | + break; |
| 1783 | + } |
| 1784 | + default: return luaL_error(L, "wrong number of arguments"); |
| 1785 | + } |
| 1786 | + return 1; |
| 1787 | +} |
| 1788 | +/* }}} */ |
| 1789 | + |
| 1790 | +/** {{{ luasandbox_math_randomseed |
| 1791 | + * |
| 1792 | + * Set the seed for the custom math.random. |
| 1793 | + */ |
| 1794 | +static int luasandbox_math_randomseed(lua_State * L) |
| 1795 | +{ |
| 1796 | + php_luasandbox_obj * sandbox = luasandbox_get_php_obj(L); |
| 1797 | + sandbox->random_seed = (unsigned int)luaL_checkint(L, 1); |
| 1798 | +} |
| 1799 | +/* }}} */ |
1740 | 1800 | /* |
1741 | 1801 | * Local variables: |
1742 | 1802 | * tab-width: 4 |