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:
helixhorned 2012-11-25 13:18:52 +00:00
parent 8293e72a95
commit dacf2695ff
4 changed files with 110 additions and 91 deletions

View file

@ -8,6 +8,7 @@ local ffiC = ffi.C
local string = string
local table = table
local print = print
--== 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
-- use this function.
--
-- NOTE: don't declare multiple pointers on one line (this is bad: "int32_t *a, *b")
-- and array *arguments* should be separated by a space, like
-- "int func(char arrayarg [16])"
-- Notes: do not declare multiple pointers on one line (this is bad:
-- "int32_t *a, *b"). Do not name array arguments (or add a space
-- between the identifier and the '[' instead).
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
-- print("DUMMY "..varname)
gv_[varname] = dummy_empty_table
@ -97,9 +100,8 @@ enum {
};
]]
ffi.cdef([[
ffi.cdef[[
#pragma pack(push,1)
struct action {
int16_t startframe, numframes;
int16_t viewtype, incval, delay;
@ -118,18 +120,18 @@ typedef struct {
con_move_t mov;
int32_t movflags;
} con_ai_t;
// TODO: still need to make some fields read-only
// NOTE: must not expose arrays in structs!!!
typedef struct
{
#pragma pack(pop)
]]
..repeat_n_elts("int32_t", "_t", 10)..
[[
// const int32_t t_data[10]; // 56b sometimes used to hold offsets to con code
-- Struct template for actor_t. It already has 'const' fields (TODO: might need
-- 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 action ac;
const int16_t _padding;
const int16_t _padding[1];
int16_t picnum,ang,extra,owner; //8b
int16_t movflag,tempang,timetosleep; //6b
@ -140,33 +142,12 @@ typedef struct
const int16_t lightId, lightcount, lightmaxrange, cgg; //8b
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];
} actor_u_t;
}
]]
typedef struct {
local DUKEPLAYER_STRUCT = [[
{
vec3_t pos, opos, vel, npos;
int32_t bobposx, bobposy;
int32_t truefz, truecz, player_par;
@ -180,19 +161,15 @@ typedef struct {
uint16_t max_actors_killed, actors_killed;
uint16_t gotweapon, zoom;
]]
..repeat_n_elts("int16_t", "_lx", 64)..repeat_n_elts("int16_t", "_ly", 64)..
[[
// int16_t loogiex[64], loogiey[64];
const int16_t loogiex[64];
const int16_t loogiey[64];
int16_t sbs, sound_pitch;
int16_t ang, oang, angvel, cursectnum, look_ang, last_extra, subweapon;
]]
..repeat_n_elts("int16_t", "_ma", ffiC.MAX_WEAPONS)
..repeat_n_elts("int16_t", "_aa", ffiC.MAX_WEAPONS)
..repeat_n_elts("int16_t", "_ia", ffiC.GET_MAX)..
[[
// int16_t max_ammo_amount[MAX_WEAPONS], ammo_amount[MAX_WEAPONS], inv_amount[GET_MAX];
const int16_t max_ammo_amount[MAX_WEAPONS];
const int16_t ammo_amount[MAX_WEAPONS];
const int16_t inv_amount[GET_MAX];
int16_t wackedbyactor, pyoff, opyoff;
int16_t horiz, horizoff, ohoriz, ohorizoff;
@ -203,10 +180,8 @@ typedef struct {
int16_t random_club_frame, one_eighty_count;
int16_t dummyplayersprite, extra_extra8;
int16_t actorsqu, timebeforeexit, customexitsound, last_pissed_time;
]]
..repeat_n_elts("int16_t", "_w", ffiC.MAX_WEAPONS)..
[[
// int16_t weaprecs[MAX_WEAPONS];
const int16_t weaprecs[MAX_WEAPONS];
int16_t weapon_sway, crack_time, bobcounter;
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;
palette_t pals;
]]
..repeat_n_elts("char", "_n", 32)..
[[
// char name[32];
int8_t padding_;
} DukePlayer_t;
const char name[32];
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 {
uint32_t bits; // 4b
@ -394,29 +424,12 @@ void kclose(int32_t handle);
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 error = error
local ipairs = ipairs
local loadstring = loadstring
local pairs = pairs
local print = print
local rawget = rawget
local rawset = rawset
local setmetatable = setmetatable
@ -616,8 +629,6 @@ end
---=== Set up restricted global environment ===---
gv_tmp = gv_ -- required by randgen
local allowed_modules = {
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,
},
randgen = require("randgen"),
randgen = randgen,
geom = require("geom"),
stat = require("stat"),
bitar = require("bitar"),

View file

@ -142,8 +142,6 @@ end
local LABEL = { MOVE=2, AI=3, ACTION=5, [2]="move", [3]="ai", [5]="action",
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
local LABEL_FUNCNAME = { [2]="move", [3]="ai", [5]="action" }
@ -235,8 +233,6 @@ local function lookup_composite(labeltype, pos, identifier)
return "_WRONGTYPE"
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.
val = string.format("%q", identifier)
@ -757,7 +753,7 @@ local Ci = {
function(str, ...) return string.format("actor[_aci]:set_move(%s)", str) end,
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),
cstator = cmd(D),
cstat = cmd(D),

View file

@ -6,20 +6,31 @@ local ffiC = ffi.C
local rawset = rawset
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
module(...)
-- NOTE: PRNG state struct and functions are declared in defs.ilua
-- PRNG state struct
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]; 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 = {
__tostring = function(s)
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")
repeat
tin.d[0] = gv.gethitickms() % 1
tin.d[1] = gv.gethitickms() % 1
tin.d[0] = ffiC.gethitickms() % 1
tin.d[1] = ffiC.gethitickms() % 1
ffiC.md4once(tin.u, 16, tout.u)

View file

@ -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("do local bt=require'bittest'; bt.QWE=1; end", "modifying module table forbidden")
-- the cdata returned by player[] is not a pointer!
checkfail("do local pl=player[0]; i=pl[1]")
-- the cdata returned by player[] can't be made into a pointer!
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))