From 7a02c6b9c28ed9a035d4473c6fa520469f64f340 Mon Sep 17 00:00:00 2001 From: David Anderson <dvander@alliedmods.net> Date: Mon, 3 Sep 2007 17:55:43 +0000 Subject: [PATCH] fixed JIT portion of amb887 - dynamic local arrays with more than 3 dimensions (i.e. >=3 levels of indirection) would have bad indirection tables, corrupting memory and/or crashing on r/w --HG-- extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/trunk%401402 --- sourcepawn/jit/x86/jit_x86.h | 2 + sourcepawn/jit/x86/opcode_helpers.cpp | 111 ++++++++++++++++++-------- 2 files changed, 80 insertions(+), 33 deletions(-) diff --git a/sourcepawn/jit/x86/jit_x86.h b/sourcepawn/jit/x86/jit_x86.h index a8d4fd47..1bdc1311 100644 --- a/sourcepawn/jit/x86/jit_x86.h +++ b/sourcepawn/jit/x86/jit_x86.h @@ -31,6 +31,8 @@ using namespace SourcePawn; #define JITVARS_FUNCINFO 1 //important: don't change this aWOAWOGJQG I LIKE HAM #define JITVARS_REBASE 2 //important: hi, i'm bail +#define sDIMEN_MAX 5 //this must mirror what the compiler has. + typedef struct tracker_s { size_t size; diff --git a/sourcepawn/jit/x86/opcode_helpers.cpp b/sourcepawn/jit/x86/opcode_helpers.cpp index 7905698e..c9327611 100644 --- a/sourcepawn/jit/x86/opcode_helpers.cpp +++ b/sourcepawn/jit/x86/opcode_helpers.cpp @@ -482,44 +482,89 @@ void WriteOp_Sysreq_C_Function(JitWriter *jit) IA32_Return(jit); } -void GenerateArrayIndirectionVectors(cell_t *arraybase, cell_t dims[], ucell_t _dimcount, bool autozero) +typedef struct array_creation_s { - cell_t vectors = 1; /* we need one vector to start off with */ - cell_t cur_offs = 0; - cell_t cur_write = 0; - cell_t dimcount = _dimcount; + const cell_t *dim_list; /* Dimension sizes */ + cell_t dim_count; /* Number of dimensions */ + cell_t *data_offs; /* Current offset AFTER the indirection vectors (data) */ + cell_t *base; /* array base */ +} array_creation_t; - /* Initialize rotation */ - cur_write = dims[dimcount-1]; +cell_t _GenerateArrayIndirectionVectors(array_creation_t *ar, int dim, cell_t cur_offs) +{ + cell_t write_offs = cur_offs; + cell_t *data_offs = ar->data_offs; + + cur_offs += ar->dim_list[dim]; + + /** + * Dimension n-x where x > 2 will have sub-vectors. + * Otherwise, we just need to reference the data section. + */ + if (dim < ar->dim_count - 2) + { + /** + * For each index at this dimension, write offstes to our sub-vectors. + * After we write one sub-vector, we generate its sub-vectors recursively. + * At the end, we're given the next offset we can use. + */ + for (int i = 0; i < ar->dim_list[dim]; i++) + { + ar->base[write_offs] = (cur_offs - write_offs) * sizeof(cell_t); + write_offs++; + cur_offs = _GenerateArrayIndirectionVectors(ar, dim + 1, cur_offs); + } + } else { + /** + * In this section, there are no sub-vectors, we need to write offsets + * to the data. This is separate so the data stays in one big chunk. + * The data offset will increment by the size of the last dimension, + * because that is where the data is finally computed as. + */ + for (int i = 0; i < ar->dim_list[dim]; i++) + { + ar->base[write_offs] = (*data_offs - write_offs) * sizeof(cell_t); + write_offs++; + *data_offs = *data_offs + ar->dim_list[dim + 1]; + } + } + + return cur_offs; +} + +static cell_t calc_indirection(const array_creation_t *ar, cell_t dim) +{ + cell_t size = ar->dim_list[dim]; + + if (dim < ar->dim_count - 2) + { + size += ar->dim_list[dim] * calc_indirection(ar, dim + 1); + } + + return size; +} + +void GenerateArrayIndirectionVectors(cell_t *arraybase, cell_t dims[], cell_t _dimcount, bool autozero) +{ + array_creation_t ar; + cell_t data_offs; + + /* Reverse the dimensions */ + cell_t dim_list[sDIMEN_MAX]; + int cur_dim = 0; + for (int i = _dimcount - 1; i >= 0; i--) + { + dim_list[cur_dim++] = dims[i]; + } - while (--dimcount >= 1) - { - cell_t cur_dim = dims[dimcount]; - cell_t sub_dim = dims[dimcount-1]; - for (cell_t i=0; i<vectors; i++) - { - for (cell_t j=0; j<cur_dim; j++) - { - arraybase[cur_offs] = (cur_write - cur_offs)*sizeof(cell_t); - cur_offs++; - cur_write += sub_dim; - } - } - vectors = cur_dim; - } + ar.base = arraybase; + ar.dim_list = dim_list; + ar.dim_count = _dimcount; + ar.data_offs = &data_offs; - /* everything after cur_offs can be zeroed */ - if (autozero) - { - size_t size = 1; - for (ucell_t i=0; i<_dimcount; i++) - { - size *= dims[i]; - } - memset(&arraybase[cur_offs], 0, size*sizeof(cell_t)); - } + data_offs = calc_indirection(&ar, 0); - return; + _GenerateArrayIndirectionVectors(&ar, 0, 0); } /**