Branch: Tag:

2001-07-03

2001-07-03 15:04:51 by Henrik Grubbström (Grubba) <grubba@grubba.org>

Added some detection of recursion in decode_value().
Improved error-handling in {encode,decode}_value().

Rev: src/encode.c:1.107

25:   #include "version.h"   #include "bignum.h"    - RCSID("$Id: encode.c,v 1.106 2001/07/03 08:04:59 hubbe Exp $"); + RCSID("$Id: encode.c,v 1.107 2001/07/03 15:04:51 grubba Exp $");      /* #define ENCODE_DEBUG */   
769:    return;    }    } -  Pike_error("Failed to encode function.\n"); +  Pike_error("Encoding of efuns is not supported yet.\n");    }       code_entry(type_to_tag(val->type), 0,data);
850:    pop_stack();      #define FOO(X,Y,Z) \ -  code_number( p->num_##Z, data); +  code_number( p->PIKE_CONCAT(num_,Z), data);   #include "program_areas.h"       adddata2(p->program, p->num_program);
894:    }else if(p->inherits[d].prog){    ref_push_program(p->inherits[d].prog);    }else{ +  Pike_error("Failed to encode inherit #%d\n", d);    push_int(0);    }    encode_value2(Pike_sp-1,data);
914:    code_number(p->identifiers[d].identifier_flags,data);    code_number(p->identifiers[d].run_time_type,data);    code_number(p->identifiers[d].opt_flags,data); +  if (!(p->identifiers[d].identifier_flags & IDENTIFIER_C_FUNCTION)) {    code_number(p->identifiers[d].func.offset,data); -  +  } else { +  Pike_error("Cannot encode functions implemented in C " +  "(identifier='%s').\n", +  p->identifiers[d].name->str);    } -  +  }       for(d=0;d<p->num_constants;d++)    {
1068:    struct svalue counter;    struct object *codec;    int pickyness; +  struct pike_string *raw; +  struct decode_data *next;   };      static void decode_value2(struct decode_data *data);
1829:    default:    Pike_error("Program decode failed!\n");    } -  if(p->parent) add_ref(p->parent); +  if(p->parent) { +  add_ref(p->parent); +  p->parent_program_id = p->parent->id; +  }    pop_stack();       debug_malloc_touch(p);
2004:    decode_number(p->identifiers[d].identifier_flags,data);    decode_number(p->identifiers[d].run_time_type,data);    decode_number(p->identifiers[d].opt_flags,data); +  if (!(p->identifiers[d].identifier_flags & IDENTIFIER_C_FUNCTION)) +  {    decode_number(p->identifiers[d].func.offset,data); -  +  } else { +  Pike_error("Cannot decode functions implemented in C " +  "(identifier='%s').\n", +  p->identifiers[d].name->str);    } -  +  }          UNSET_ONERROR(err2);
2151:   }       + static struct decode_data *current_decode = NULL; +    static void free_decode_data(struct decode_data *data)   {    free_mapping(data->decoded);
2160:    data->unfinished_programs=tmp->next;    free((char *)tmp);    } +  if (current_decode == data) { +  current_decode = data->next; +  } else { +  struct decode_data *d; +  for (d = current_decode; d; d=d->next) { +  if (d->next == data) { +  d->next = d->next->next; +  break;    } -  +  } + #ifdef PIKE_DEBUG +  if (!d) { +  fatal("Decode data fell off the stack!\n"); +  } + #endif /* PIKE_DEBUG */ +  } + }      static INT32 my_decode(struct pike_string *tmp,    struct object *codec)   {    ONERROR err;    struct decode_data d, *data; -  +  +  /* Attempt to avoid infinite recursion on circular structures. */ +  for (data = current_decode; data; data=data->next) { +  if (data->raw == tmp) { +  struct svalue *res; +  struct svalue val = { +  T_INT, NUMBER_NUMBER, + #ifdef HAVE_UNION_INIT +  {0}, /* Only to avoid warnings. */ + #endif /* HAVE_UNION_INIT */ +  }; +  val.u.integer = 0; +  if ((res = low_mapping_lookup(data->decoded, &val))) { +  push_svalue(res); +  return 1; +  } +  /* Possible recursion detected. */ +  /* return 0; */ +  } +  } +     data=&d;    data->counter.type=T_INT;    data->counter.u.integer=COUNTER_START;
2176:    data->codec=codec;    data->pickyness=0;    data->unfinished_programs=0; +  data->raw = tmp; +  data->next = current_decode;       if (tmp->size_shift) return 0;    if(data->len < 5) return 0;
2187:       data->decoded=allocate_mapping(128);    +  current_decode = data; +     SET_ONERROR(err, free_decode_data, data);    decode_value2(data); -  UNSET_ONERROR(err); +    #ifdef PIKE_DEBUG    if(data->unfinished_programs)    fatal("We have unfinished programs left in decode()! We may need a double loop!\n");   #endif -  free_mapping(data->decoded); +  CALL_AND_UNSET_ONERROR(err);    return 1;   }