mirror of
https://github.com/ZDoom/raze-gles.git
synced 2025-01-11 10:40:47 +00:00
Lunatic: better protection of array members inside structs.
git-svn-id: https://svn.eduke32.com/eduke32@3227 1a8010ca-5511-0410-912e-c29ae57300e0
This commit is contained in:
parent
8293e72a95
commit
dacf2695ff
4 changed files with 110 additions and 91 deletions
|
@ -8,6 +8,7 @@ local ffiC = ffi.C
|
||||||
|
|
||||||
local string = string
|
local string = string
|
||||||
local table = table
|
local table = table
|
||||||
|
local print = print
|
||||||
|
|
||||||
--== First, load the definitions common to the game's and editor's Lua interface.
|
--== First, load the definitions common to the game's and editor's Lua interface.
|
||||||
|
|
||||||
|
@ -24,10 +25,12 @@ local dummy_empty_table = {}
|
||||||
-- accessible through the "gv" global. The "defs_common" module will
|
-- accessible through the "gv" global. The "defs_common" module will
|
||||||
-- use this function.
|
-- use this function.
|
||||||
--
|
--
|
||||||
-- NOTE: don't declare multiple pointers on one line (this is bad: "int32_t *a, *b")
|
-- Notes: do not declare multiple pointers on one line (this is bad:
|
||||||
-- and array *arguments* should be separated by a space, like
|
-- "int32_t *a, *b"). Do not name array arguments (or add a space
|
||||||
-- "int func(char arrayarg [16])"
|
-- between the identifier and the '[' instead).
|
||||||
function decl(str)
|
function decl(str)
|
||||||
|
-- NOTE that the regexp also catches non-array/non-function identifiers
|
||||||
|
-- like "user_defs ud;"
|
||||||
for varname in string.gmatch(str, "([%a_][%w_]*)[[(;]") do
|
for varname in string.gmatch(str, "([%a_][%w_]*)[[(;]") do
|
||||||
-- print("DUMMY "..varname)
|
-- print("DUMMY "..varname)
|
||||||
gv_[varname] = dummy_empty_table
|
gv_[varname] = dummy_empty_table
|
||||||
|
@ -97,9 +100,8 @@ enum {
|
||||||
};
|
};
|
||||||
]]
|
]]
|
||||||
|
|
||||||
ffi.cdef([[
|
ffi.cdef[[
|
||||||
#pragma pack(push,1)
|
#pragma pack(push,1)
|
||||||
|
|
||||||
struct action {
|
struct action {
|
||||||
int16_t startframe, numframes;
|
int16_t startframe, numframes;
|
||||||
int16_t viewtype, incval, delay;
|
int16_t viewtype, incval, delay;
|
||||||
|
@ -118,18 +120,18 @@ typedef struct {
|
||||||
con_move_t mov;
|
con_move_t mov;
|
||||||
int32_t movflags;
|
int32_t movflags;
|
||||||
} con_ai_t;
|
} con_ai_t;
|
||||||
|
#pragma pack(pop)
|
||||||
// TODO: still need to make some fields read-only
|
|
||||||
// NOTE: must not expose arrays in structs!!!
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
]]
|
]]
|
||||||
..repeat_n_elts("int32_t", "_t", 10)..
|
|
||||||
[[
|
-- Struct template for actor_t. It already has 'const' fields (TODO: might need
|
||||||
// const int32_t t_data[10]; // 56b sometimes used to hold offsets to con code
|
-- to make more 'const'), but still has array members exposed, so is unsuited
|
||||||
|
-- for external exposure.
|
||||||
|
local ACTOR_STRUCT = [[
|
||||||
|
{
|
||||||
|
const int32_t t_data[10]; // 56b sometimes used to hold offsets to con code
|
||||||
const struct move mv;
|
const struct move mv;
|
||||||
const struct action ac;
|
const struct action ac;
|
||||||
const int16_t _padding;
|
const int16_t _padding[1];
|
||||||
|
|
||||||
int16_t picnum,ang,extra,owner; //8b
|
int16_t picnum,ang,extra,owner; //8b
|
||||||
int16_t movflag,tempang,timetosleep; //6b
|
int16_t movflag,tempang,timetosleep; //6b
|
||||||
|
@ -140,33 +142,12 @@ typedef struct
|
||||||
|
|
||||||
const int16_t lightId, lightcount, lightmaxrange, cgg; //8b
|
const int16_t lightId, lightcount, lightmaxrange, cgg; //8b
|
||||||
int16_t actorstayput, dispicnum, shootzvel; // 6b
|
int16_t actorstayput, dispicnum, shootzvel; // 6b
|
||||||
]]
|
|
||||||
..repeat_n_elts("int8_t", "_d", 8)..
|
|
||||||
[[
|
|
||||||
// const int8_t _do_not_use[8];
|
|
||||||
} actor_t;
|
|
||||||
|
|
||||||
// The _u_t versions are unrestricted variants for internal use.
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
int32_t t_data[10];
|
|
||||||
struct move mv;
|
|
||||||
struct action ac;
|
|
||||||
const int16_t padding_;
|
|
||||||
|
|
||||||
int16_t picnum,ang,extra,owner;
|
|
||||||
int16_t movflag,tempang,timetosleep;
|
|
||||||
|
|
||||||
int32_t flags, bposx,bposy,bposz;
|
|
||||||
int32_t floorz,ceilingz,lastvx,lastvy;
|
|
||||||
int32_t lasttransport;
|
|
||||||
|
|
||||||
int16_t lightId, lightcount, lightmaxrange, cgg;
|
|
||||||
int16_t actorstayput, dispicnum, shootzvel;
|
|
||||||
const int8_t _do_not_use[8];
|
const int8_t _do_not_use[8];
|
||||||
} actor_u_t;
|
}
|
||||||
|
]]
|
||||||
|
|
||||||
typedef struct {
|
local DUKEPLAYER_STRUCT = [[
|
||||||
|
{
|
||||||
vec3_t pos, opos, vel, npos;
|
vec3_t pos, opos, vel, npos;
|
||||||
int32_t bobposx, bobposy;
|
int32_t bobposx, bobposy;
|
||||||
int32_t truefz, truecz, player_par;
|
int32_t truefz, truecz, player_par;
|
||||||
|
@ -180,19 +161,15 @@ typedef struct {
|
||||||
|
|
||||||
uint16_t max_actors_killed, actors_killed;
|
uint16_t max_actors_killed, actors_killed;
|
||||||
uint16_t gotweapon, zoom;
|
uint16_t gotweapon, zoom;
|
||||||
]]
|
|
||||||
..repeat_n_elts("int16_t", "_lx", 64)..repeat_n_elts("int16_t", "_ly", 64)..
|
const int16_t loogiex[64];
|
||||||
[[
|
const int16_t loogiey[64];
|
||||||
// int16_t loogiex[64], loogiey[64];
|
|
||||||
int16_t sbs, sound_pitch;
|
int16_t sbs, sound_pitch;
|
||||||
|
|
||||||
int16_t ang, oang, angvel, cursectnum, look_ang, last_extra, subweapon;
|
int16_t ang, oang, angvel, cursectnum, look_ang, last_extra, subweapon;
|
||||||
]]
|
const int16_t max_ammo_amount[MAX_WEAPONS];
|
||||||
..repeat_n_elts("int16_t", "_ma", ffiC.MAX_WEAPONS)
|
const int16_t ammo_amount[MAX_WEAPONS];
|
||||||
..repeat_n_elts("int16_t", "_aa", ffiC.MAX_WEAPONS)
|
const int16_t inv_amount[GET_MAX];
|
||||||
..repeat_n_elts("int16_t", "_ia", ffiC.GET_MAX)..
|
|
||||||
[[
|
|
||||||
// int16_t max_ammo_amount[MAX_WEAPONS], ammo_amount[MAX_WEAPONS], inv_amount[GET_MAX];
|
|
||||||
int16_t wackedbyactor, pyoff, opyoff;
|
int16_t wackedbyactor, pyoff, opyoff;
|
||||||
|
|
||||||
int16_t horiz, horizoff, ohoriz, ohorizoff;
|
int16_t horiz, horizoff, ohoriz, ohorizoff;
|
||||||
|
@ -203,10 +180,8 @@ typedef struct {
|
||||||
int16_t random_club_frame, one_eighty_count;
|
int16_t random_club_frame, one_eighty_count;
|
||||||
int16_t dummyplayersprite, extra_extra8;
|
int16_t dummyplayersprite, extra_extra8;
|
||||||
int16_t actorsqu, timebeforeexit, customexitsound, last_pissed_time;
|
int16_t actorsqu, timebeforeexit, customexitsound, last_pissed_time;
|
||||||
]]
|
|
||||||
..repeat_n_elts("int16_t", "_w", ffiC.MAX_WEAPONS)..
|
const int16_t weaprecs[MAX_WEAPONS];
|
||||||
[[
|
|
||||||
// int16_t weaprecs[MAX_WEAPONS];
|
|
||||||
int16_t weapon_sway, crack_time, bobcounter;
|
int16_t weapon_sway, crack_time, bobcounter;
|
||||||
|
|
||||||
int16_t orotscrnang, rotscrnang, dead_flag; // JBF 20031220: added orotscrnang
|
int16_t orotscrnang, rotscrnang, dead_flag; // JBF 20031220: added orotscrnang
|
||||||
|
@ -236,13 +211,68 @@ typedef struct {
|
||||||
int8_t last_weapon, cheat_phase, weapon_pos, wantweaponfire, curr_weapon;
|
int8_t last_weapon, cheat_phase, weapon_pos, wantweaponfire, curr_weapon;
|
||||||
|
|
||||||
palette_t pals;
|
palette_t pals;
|
||||||
]]
|
|
||||||
..repeat_n_elts("char", "_n", 32)..
|
|
||||||
[[
|
|
||||||
// char name[32];
|
|
||||||
|
|
||||||
int8_t padding_;
|
const char name[32];
|
||||||
} DukePlayer_t;
|
|
||||||
|
const int8_t padding_[1];
|
||||||
|
}
|
||||||
|
]]
|
||||||
|
|
||||||
|
local randgen = require("randgen")
|
||||||
|
|
||||||
|
-- Converts a template struct definition to an internal, unrestricted one.
|
||||||
|
local function strip_const(structstr)
|
||||||
|
return string.gsub(structstr, "const ", "");
|
||||||
|
end
|
||||||
|
|
||||||
|
local ma_rand = randgen.new(true) -- initialize to "random" (time-based) seed
|
||||||
|
local ma_count = nil
|
||||||
|
|
||||||
|
local function ma_replace_array(typestr, neltstr)
|
||||||
|
local nelts = tonumber(neltstr)
|
||||||
|
if (nelts==nil) then
|
||||||
|
nelts = ffiC[neltstr]
|
||||||
|
assert(type(nelts)=="number")
|
||||||
|
end
|
||||||
|
|
||||||
|
local strtab = { "const ", typestr.." " }
|
||||||
|
for i=1,nelts do
|
||||||
|
local ch1 = 97 + (ma_rand:getu32() % 25) -- 'a'..'z'
|
||||||
|
strtab[i+2] = string.format("_%c%x%s", ch1, ma_count, (i<nelts) and "," or "")
|
||||||
|
ma_count = ma_count+1
|
||||||
|
end
|
||||||
|
strtab[#strtab+1] = ";"
|
||||||
|
|
||||||
|
return table.concat(strtab)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Converts a template struct definition to an external one, in which arrays
|
||||||
|
-- have been substituted by randomly named scalar fields.
|
||||||
|
local function mangle_arrays(structstr)
|
||||||
|
ma_count = 0
|
||||||
|
-- NOTE: regexp only works for non-nested arrays and for one array per line.
|
||||||
|
return (string.gsub(structstr, "const%s+([%w_]+)[^\n]+%[([%w_]+)%];", ma_replace_array))
|
||||||
|
end
|
||||||
|
|
||||||
|
--print(mangle_arrays(ACTOR_STRUCT))
|
||||||
|
|
||||||
|
ffi.cdef([[
|
||||||
|
#pragma pack(push, 1)
|
||||||
|
typedef struct
|
||||||
|
]].. mangle_arrays(ACTOR_STRUCT) ..[[
|
||||||
|
actor_t;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
]].. strip_const(ACTOR_STRUCT).. [[
|
||||||
|
actor_u_t; // The _u_t versions are unrestricted variants for internal use.
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
]].. mangle_arrays(DUKEPLAYER_STRUCT) ..[[
|
||||||
|
DukePlayer_t;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
]].. strip_const(DUKEPLAYER_STRUCT) ..[[
|
||||||
|
DukePlayer_u_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint32_t bits; // 4b
|
uint32_t bits; // 4b
|
||||||
|
@ -394,29 +424,12 @@ void kclose(int32_t handle);
|
||||||
int32_t kread(int32_t handle, void *buffer, int32_t leng);
|
int32_t kread(int32_t handle, void *buffer, int32_t leng);
|
||||||
]]
|
]]
|
||||||
|
|
||||||
-- JKISS PRNG state struct and functions, see randgen module
|
|
||||||
ffi.cdef[[
|
|
||||||
typedef struct {
|
|
||||||
uint32_t x, y, z, c;
|
|
||||||
} rng_jkiss_t;
|
|
||||||
]]
|
|
||||||
decl[[
|
|
||||||
uint32_t rand_jkiss_u32(rng_jkiss_t *s);
|
|
||||||
double rand_jkiss_dbl(rng_jkiss_t *s);
|
|
||||||
|
|
||||||
void md4once(const unsigned char *block, unsigned int len, unsigned char digest [16]);
|
|
||||||
]]
|
|
||||||
-- ^^^ The space between 'digest' and '[16]' is so that it's not added to the
|
|
||||||
-- dummy_empty_table (see regexp in decl()).
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
local assert = assert
|
local assert = assert
|
||||||
local error = error
|
local error = error
|
||||||
local ipairs = ipairs
|
local ipairs = ipairs
|
||||||
local loadstring = loadstring
|
local loadstring = loadstring
|
||||||
local pairs = pairs
|
local pairs = pairs
|
||||||
local print = print
|
|
||||||
local rawget = rawget
|
local rawget = rawget
|
||||||
local rawset = rawset
|
local rawset = rawset
|
||||||
local setmetatable = setmetatable
|
local setmetatable = setmetatable
|
||||||
|
@ -616,8 +629,6 @@ end
|
||||||
|
|
||||||
---=== Set up restricted global environment ===---
|
---=== Set up restricted global environment ===---
|
||||||
|
|
||||||
gv_tmp = gv_ -- required by randgen
|
|
||||||
|
|
||||||
local allowed_modules = {
|
local allowed_modules = {
|
||||||
coroutine=coroutine, bit=bit, table=table, math=math, string=string,
|
coroutine=coroutine, bit=bit, table=table, math=math, string=string,
|
||||||
|
|
||||||
|
@ -625,7 +636,7 @@ local allowed_modules = {
|
||||||
clock = function() return gv_.gethitickms()*0.001 end,
|
clock = function() return gv_.gethitickms()*0.001 end,
|
||||||
},
|
},
|
||||||
|
|
||||||
randgen = require("randgen"),
|
randgen = randgen,
|
||||||
geom = require("geom"),
|
geom = require("geom"),
|
||||||
stat = require("stat"),
|
stat = require("stat"),
|
||||||
bitar = require("bitar"),
|
bitar = require("bitar"),
|
||||||
|
|
|
@ -142,8 +142,6 @@ end
|
||||||
local LABEL = { MOVE=2, AI=3, ACTION=5, [2]="move", [3]="ai", [5]="action",
|
local LABEL = { MOVE=2, AI=3, ACTION=5, [2]="move", [3]="ai", [5]="action",
|
||||||
NUMBER=1, [1]="number" }
|
NUMBER=1, [1]="number" }
|
||||||
|
|
||||||
-- Table names in the 'con' module
|
|
||||||
--local LABEL_TABNAME = { [2]="MV", [3]="AI", [5]="AC" }
|
|
||||||
-- Function names in the 'con' module
|
-- Function names in the 'con' module
|
||||||
local LABEL_FUNCNAME = { [2]="move", [3]="ai", [5]="action" }
|
local LABEL_FUNCNAME = { [2]="move", [3]="ai", [5]="action" }
|
||||||
|
|
||||||
|
@ -235,8 +233,6 @@ local function lookup_composite(labeltype, pos, identifier)
|
||||||
return "_WRONGTYPE"
|
return "_WRONGTYPE"
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Generate a lookup into the control module's move/action/ai defs.
|
|
||||||
-- val = string.format("_con.%s[%q]", LABEL_TABNAME[labeltype], identifier)
|
|
||||||
-- Generate a quoted identifier name.
|
-- Generate a quoted identifier name.
|
||||||
val = string.format("%q", identifier)
|
val = string.format("%q", identifier)
|
||||||
|
|
||||||
|
@ -757,7 +753,7 @@ local Ci = {
|
||||||
function(str, ...) return string.format("actor[_aci]:set_move(%s)", str) end,
|
function(str, ...) return string.format("actor[_aci]:set_move(%s)", str) end,
|
||||||
|
|
||||||
cactor = cmd(D) /
|
cactor = cmd(D) /
|
||||||
"sprite[_aci].tilenum=%1",
|
"sprite[_aci].tilenum=%1", -- TODO: wrap, e.g. sprite[]:set_picnum(tilenum), bound check there
|
||||||
count = cmd(D),
|
count = cmd(D),
|
||||||
cstator = cmd(D),
|
cstator = cmd(D),
|
||||||
cstat = cmd(D),
|
cstat = cmd(D),
|
||||||
|
|
|
@ -6,20 +6,31 @@ local ffiC = ffi.C
|
||||||
local rawset = rawset
|
local rawset = rawset
|
||||||
|
|
||||||
local type = type
|
local type = type
|
||||||
local gv = gv_tmp -- temporarily set in defs.c
|
local decl = decl -- comes from above (defs.ilua)
|
||||||
|
|
||||||
local print = print -- for commented out debug block in new() below
|
local print = print -- for commented out debug block in new() below
|
||||||
|
|
||||||
module(...)
|
module(...)
|
||||||
|
|
||||||
|
|
||||||
-- NOTE: PRNG state struct and functions are declared in defs.ilua
|
-- PRNG state struct
|
||||||
|
|
||||||
ffi.cdef[[
|
ffi.cdef[[
|
||||||
|
typedef struct {
|
||||||
|
uint32_t x, y, z, c;
|
||||||
|
} rng_jkiss_t;
|
||||||
|
|
||||||
typedef union { unsigned char u[16]; double d[2]; } uchar_double_u_t;
|
typedef union { unsigned char u[16]; double d[2]; } uchar_double_u_t;
|
||||||
typedef union { unsigned char u[16]; uint32_t i[4]; } uchar_uint_u_t;
|
typedef union { unsigned char u[16]; uint32_t i[4]; } uchar_uint_u_t;
|
||||||
]]
|
]]
|
||||||
|
|
||||||
|
-- PRNG functions
|
||||||
|
decl[[
|
||||||
|
uint32_t rand_jkiss_u32(rng_jkiss_t *s);
|
||||||
|
double rand_jkiss_dbl(rng_jkiss_t *s);
|
||||||
|
|
||||||
|
void md4once(const unsigned char *block, unsigned int len, unsigned char digest [16]);
|
||||||
|
]]
|
||||||
|
|
||||||
local mt = {
|
local mt = {
|
||||||
__tostring = function(s)
|
__tostring = function(s)
|
||||||
return "rand.new("..s.x..","..s.y..","..s.z..","..s.c..")"
|
return "rand.new("..s.x..","..s.y..","..s.z..","..s.c..")"
|
||||||
|
@ -36,8 +47,8 @@ local mt = {
|
||||||
local tout = ffi.new("uchar_uint_u_t")
|
local tout = ffi.new("uchar_uint_u_t")
|
||||||
|
|
||||||
repeat
|
repeat
|
||||||
tin.d[0] = gv.gethitickms() % 1
|
tin.d[0] = ffiC.gethitickms() % 1
|
||||||
tin.d[1] = gv.gethitickms() % 1
|
tin.d[1] = ffiC.gethitickms() % 1
|
||||||
|
|
||||||
ffiC.md4once(tin.u, 16, tout.u)
|
ffiC.md4once(tin.u, 16, tout.u)
|
||||||
|
|
||||||
|
|
|
@ -179,8 +179,9 @@ checkfail('local spr = sprite[0]; local x=spr+1', "attempt to perform arithmetic
|
||||||
checkfail('gameactor(1680, 0)', "bad argument #3 to 'gameactor' (function expected, got number)")
|
checkfail('gameactor(1680, 0)', "bad argument #3 to 'gameactor' (function expected, got number)")
|
||||||
|
|
||||||
checkfail("do local bt=require'bittest'; bt.QWE=1; end", "modifying module table forbidden")
|
checkfail("do local bt=require'bittest'; bt.QWE=1; end", "modifying module table forbidden")
|
||||||
-- the cdata returned by player[] is not a pointer!
|
-- the cdata returned by player[] can't be made into a pointer!
|
||||||
checkfail("do local pl=player[0]; i=pl[1]")
|
checkfail("do local pl=player[0]; i=pl[1]; end")
|
||||||
|
checkfail("do local ud=gv.ud.camera; end", "dummy variable: read access forbidden") -- test for proper decl()
|
||||||
|
|
||||||
printf('ceilingbunch of sector 0: %d', getbunch(0, gv.CEILING))
|
printf('ceilingbunch of sector 0: %d', getbunch(0, gv.CEILING))
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue