Commit 32088b32 authored by Bernhard Link's avatar Bernhard Link

add SIZE directive to give explicit sizes

parent 7ee880b1
2011-01-29
* add a 'SIZE' directive to limit some structure to an explicit size
(in VarStructs everything after that size is printed as unexpected
data and otherwise ignored, also all field output or list length
is automatically truncated to that value)
2011-01-28
* allow to 'transfer' data from REQUEST to RESPONSE on the stack
* allow 'IF STORED ...' to compare stored value
......
......@@ -1052,6 +1052,7 @@ END
LIST RenderCommand variable min-length 4
0 length COUNT16
SIZE COUNT
2 command ENUM16 gl_command
IF 2 CARD16 $gl_command:Begin
4 mode glENUM
......@@ -1088,7 +1089,7 @@ ELSEIF 8 CARD32 $glENUM:4_BYTES
12 lists LISTof4BYTES
ELSE
0 n CARD16
DECREMENT_COUNT 12
RESET_COUNTER
12 strange-data LISTofCARD8
ELSEIF 2 CARD16 $gl_command:Clear
......@@ -1135,8 +1136,7 @@ ELSEIF 8 CARD32 $glENUM:QUADRATIC_ATTENUATION
NEXT 16
ELSE
8 pname CARD32
0 len COUNT16
DECREMENT_COUNT 4
RESET_COUNTER
4 unknown-light LISTofCARD8
ELSEIF 2 CARD16 $gl_command:ListBase
......@@ -1169,8 +1169,7 @@ ELSEIF 8 CARD32 $glENUM:COLOR_INDEXES
SET_COUNTER 3
12 data LISTofFLOAT32
ELSE
0 len COUNT16
DECREMENT_COUNT 12
RESET_COUNTER
12 unknown-material-data LISTofCARD8
ELSEIF 2 CARD16 $gl_command:Normal3fv
......@@ -1221,7 +1220,6 @@ NEXT 16
# TODO: all the other commands still need to be implemented
ELSE
DECREMENT_COUNT 4
4 unknown LISTofCARD8
END
......
......@@ -259,7 +259,7 @@ static size_t printSTRING8(const uint8_t *buffer,size_t buflen,const struct para
return ofs;
}
static size_t printLISTofCARD8(const uint8_t *buffer,size_t buflen,const struct parameter *p,size_t len, size_t ofs){
static size_t printLISTofCARD8(const uint8_t *buffer, size_t buflen, const char *name, const struct constant *constants, size_t len, size_t ofs){
bool notfirst = false;
size_t nr = 0;
......@@ -270,7 +270,7 @@ static size_t printLISTofCARD8(const uint8_t *buffer,size_t buflen,const struct
if( print_offsets )
fprintf(out,"[%d]",(int)ofs);
fprintf(out,"%s=",p->name);
fprintf(out, "%s=", name);
while( len > 0 ) {
const char *value;
unsigned char u8;
......@@ -282,7 +282,7 @@ static size_t printLISTofCARD8(const uint8_t *buffer,size_t buflen,const struct
putc(',',out);
notfirst = true;
u8 = getCARD8(ofs);
value = findConstant(p->constants,u8);
value = findConstant(constants, u8);
if( value )
fprintf(out,"%s(0x%hhx)",value,u8);
else
......@@ -967,8 +967,10 @@ static size_t print_parameters(struct connection *c, const unsigned char *buffer
bool printspace = false;
size_t lastofs = 0;
struct stack newstack = *oldstack;
bool sizeset = false;
for( p = parameters; p->name != NULL; p++ ) {
size_t s;
int8_t i8; int16_t i16; int32_t i32;
#ifdef STUPIDCC
uint8_t u8=0; uint16_t u16=0; uint32_t u32=0;
......@@ -1060,6 +1062,21 @@ static size_t print_parameters(struct connection *c, const unsigned char *buffer
lastofs = ofs;
printspace = false;
continue;
case ft_SET_SIZE:
printspace = false;
sizeset = true;
if( p->offse == (size_t)-1 )
s = stored;
else if( (p->offse & 0x80000000U) != 0 )
s = getFromStack(&newstack,
p->offse - 0x80000000U);
else
s = p->offse;
if( p->name != NULL && p->name[0] != '\0' )
s *= (unsigned char)(p->name[0]);
if( len > s )
len = s;
continue;
case ft_FORMAT8:
if( ofs < len )
format = getCARD8(ofs);
......@@ -1069,7 +1086,9 @@ static size_t print_parameters(struct connection *c, const unsigned char *buffer
lastofs = printSTRING8(buffer,len,p,stored,ofs);
continue;
case ft_LISTofCARD8:
lastofs = printLISTofCARD8(buffer,len,p,stored,ofs);
lastofs = printLISTofCARD8(buffer, len,
p->name, p->constants,
stored, ofs);
continue;
case ft_LISTofCARD16:
lastofs = printLISTofCARD16(c,buffer,len,p,stored,ofs);
......@@ -1101,7 +1120,9 @@ static size_t print_parameters(struct connection *c, const unsigned char *buffer
case ft_LISTofFormat:
switch( format ) {
case 8:
lastofs = printLISTofCARD8(buffer,len,p,stored,ofs);
lastofs = printLISTofCARD8(buffer, len,
p->name, p->constants,
stored, ofs);
break;
case 16:
lastofs = printLISTofCARD16(c,buffer,len,p,stored,ofs);
......@@ -1370,6 +1391,7 @@ static size_t print_parameters(struct connection *c, const unsigned char *buffer
case ft_BE32:
case ft_ATOM:
case ft_LASTMARKER:
case ft_SET_SIZE:
case ft_GET:
case ft_DECREMENT_STORED:
case ft_SET:
......@@ -1393,7 +1415,21 @@ static size_t print_parameters(struct connection *c, const unsigned char *buffer
*oldstack = newstack;
else
pop(&newstack,oldstack);
return lastofs;
if( sizeset ) {
if( lastofs < len ) {
if( printspace )
putc(' ', out);
lastofs = printLISTofCARD8(buffer, len,
"unexpected-data", NULL,
len - lastofs, lastofs);
assert( lastofs == len );
} else if( lastofs > len ) {
fprintf(out, "[strange: size-len=%d]",
(int)(lastofs-len));
}
return len;
} else
return lastofs;
}
......
......@@ -77,7 +77,7 @@ struct parameter {
ft_LISTofStruct,
/* - same but length is mininum length and
* actual length is taken from end of last list
* or LASTMARKER */
* or LASTMARKER, unless there is a SIZESET */
ft_LISTofVarStruct,
/* - like ENUM for last STORE, but constants
* are of type (struct value*) interpreteted at this
......@@ -98,6 +98,9 @@ struct parameter {
ft_IFATOM,
/* set end of last list manually, (for LISTofVarStruct) */
ft_LASTMARKER,
/* set the end of the current context, also change length
* of a VarStruct: */
ft_SET_SIZE,
/* a ft_CARD32 looking into the ATOM list */
ft_ATOM,
/* always big endian */
......
......@@ -896,17 +896,35 @@ static struct unfinished_parameter *new_parameter_special(struct parser *parser,
if nothing is accessed past the length in a struct,
if things overlap, ...
*/
struct parameter_state {
struct parameter_state *parent;
struct unfinished_parameter *junction;
size_t maxsize, minsize;
bool store_set,
store_used,
format_set,
sizemarker_set,
nextmarker_set,
nextmarker_at_end_of_packet;
};
static void field_accessed(struct parser *parser, struct parameter_state *state, size_t ofs, size_t fieldlen) {
if( ofs == (size_t)-1 )
return;
if( ofs + fieldlen > state->minsize ) {
if( ofs + fieldlen > state->maxsize ) {
error(parser, "Accessing field past specified SIZE of %lu!", (unsigned long)state->maxsize);
}
state->minsize = ofs + fieldlen;
}
/* TODO: record here what areas are used to avoid overlaps and
* gaps? */
}
static bool parse_parameters(struct parser *parser, struct variable *variable, bool needsnextmarker) {
long first_line = parser->current->lineno;
struct parameter_state {
struct parameter_state *parent;
struct unfinished_parameter *junction;
bool store_set,
store_used,
format_set,
nextmarker_set,
nextmarker_at_end_of_packet;
} *state;
struct parameter_state *state;
struct unfinished_parameter *parameters = NULL, **last = &parameters;
assert( variable->parameter == NULL );
......@@ -916,6 +934,7 @@ static bool parse_parameters(struct parser *parser, struct variable *variable, b
oom(parser);
return false;
}
state->maxsize = SIZE_MAX;
while( get_next_line(parser, first_line) ) {
const char *position, *name;
......@@ -1028,6 +1047,7 @@ static bool parse_parameters(struct parser *parser, struct variable *variable, b
struct unfinished_parameter *i;
const char *v, *condition;
enum fieldtype ft;
size_t fieldlen;
v = get_const_token(parser, false);
if( strcmp(v, "STORED") == 0 )
......@@ -1041,6 +1061,7 @@ static bool parse_parameters(struct parser *parser, struct variable *variable, b
ft = ft_IFATOM;
v = get_const_token(parser, false);
condition = string_add(v);
fieldlen = 4;
} else if( strcmp(v, "CARD8") == 0 ) {
unsigned char c;
......@@ -1048,6 +1069,7 @@ static bool parse_parameters(struct parser *parser, struct variable *variable, b
v = get_const_token(parser, false);
c = parse_number(parser, v);
condition = string_add_l((const char*)&c, 1);
fieldlen = 1;
} else if( strcmp(v, "CARD16") == 0 ) {
unsigned char c[2];
unsigned long l;
......@@ -1058,6 +1080,7 @@ static bool parse_parameters(struct parser *parser, struct variable *variable, b
c[1] = l & 0xFF;
c[0] = l >> 8;
condition = string_add_l((const char*)c, 2);
fieldlen = 2;
} else if( strcmp(v, "CARD32") == 0 ) {
unsigned char c[4];
unsigned long l;
......@@ -1070,11 +1093,13 @@ static bool parse_parameters(struct parser *parser, struct variable *variable, b
c[1] = (l >> 16) & 0xFF;
c[0] = l >> 24;
condition = string_add_l((const char*)c, 4);
fieldlen = 4;
} else {
error(parser, "unknown IF type '%s'!", v);
break;
}
no_more_arguments(parser);
field_accessed(parser, state, number, fieldlen);
i = new_parameter_special(parser, &last,
ft, number, condition);
s = malloc(sizeof(*s));
......@@ -1149,6 +1174,57 @@ static bool parse_parameters(struct parser *parser, struct variable *variable, b
ft_SET, INT_MAX, NULL);
continue;
}
if( strcmp(position, "SIZE") == 0 ) {
const char *v;
unsigned long t = 1;
v = get_const_token(parser, false);
if( v == NULL )
break;
if( strcmp(v, "STORE") == 0 || strcmp(v, "COUNT") == 0 ) {
if( !state->store_set )
error(parser, "store variable not yet set, so cannot be used!");
state->store_used = true;
number = (size_t)-1;
} else if( strcmp(v, "GET") == 0 ) {
// TODO: check if stack can have something...
number = parse_number(parser, v);
if( number >= 30 ) {
error(parser, "Absurd big stack index: %lu\n", number);
continue;
}
number |= 0x80000000;
} else {
number = parse_number(parser, v);
if( number > 65536 ) {
error(parser, "Absurd big number for length of substructure: %lu\n", number);
continue;
}
state->maxsize = number;
if( state->minsize > state->maxsize ) {
error(parser, "Setting size to %lu >= Data yet looked at up to %lu!", (unsigned long)state->maxsize, (unsigned long)state->minsize);
continue;
}
}
v = get_const_token(parser, true);
if( v != NULL ) {
if( strcmp(v, "TIMES") != 0 ) {
error(parser, "Unexpected argument '%s'!", v);
continue;
}
error(parser, "'TIMES' not yet supported!");
continue;
v = get_const_token(parser, false);
t = parse_number(parser, v);
}
no_more_arguments(parser);
state->sizemarker_set = true;
new_parameter_special(parser, &last,
ft_SET_SIZE, number, NULL);
continue;
}
if( strcmp(position, "NEXT") == 0 ) {
const char *v;
......@@ -1219,6 +1295,9 @@ static bool parse_parameters(struct parser *parser, struct variable *variable, b
(*last)->regular.offse = number;
(*last)->regular.name = string_add(name);;
(*last)->regular.type = type;
/* TODO: better size estimate for structs and for lists
* where the counter was explicitly set */
field_accessed(parser, state, number, type.base_type->size);
last = &(*last)->next;
}
error(parser, "missing END!");
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment