Browse Source

more range checking

David Rose 21 years ago
parent
commit
414ec1b386

+ 1 - 1
direct/src/dcparser/dcArrayParameter.h

@@ -49,7 +49,7 @@ public:
 
   virtual void output_instance(ostream &out, const string &prename, 
                                const string &name, const string &postname) const;
-  virtual void generate_hash(HashGenerator &hash) const;
+  virtual void generate_hash(HashGenerator &hashgen) const;
 
 private:
   DCParameter *_element_type;

+ 1 - 1
direct/src/dcparser/dcAtomicField.h

@@ -64,7 +64,7 @@ PUBLISHED:
 public:
   DCAtomicField(const string &name);
   virtual void write(ostream &out, bool brief, int indent_level) const;
-  virtual void generate_hash(HashGenerator &hash) const;
+  virtual void generate_hash(HashGenerator &hashgen) const;
 
   virtual DCPackerInterface *get_nested_field(int n) const;
 

+ 1 - 1
direct/src/dcparser/dcClass.h

@@ -86,7 +86,7 @@ public:
   ~DCClass();
 
   virtual void write(ostream &out, bool brief, int indent_level) const;
-  void generate_hash(HashGenerator &hash) const;
+  void generate_hash(HashGenerator &hashgen) const;
 
   bool add_field(DCField *field);
   bool add_parameter(DCParameter *parameter);

+ 1 - 1
direct/src/dcparser/dcClassParameter.h

@@ -47,7 +47,7 @@ public:
 
   virtual void output_instance(ostream &out, const string &prename, 
                                const string &name, const string &postname) const;
-  virtual void generate_hash(HashGenerator &hash) const;
+  virtual void generate_hash(HashGenerator &hashgen) const;
 
 private:
   DCClass *_dclass;

+ 35 - 3
direct/src/dcparser/dcField.cxx

@@ -100,6 +100,26 @@ parse_string(const string &formatted_string) {
   return packer.get_string();
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: DCField::validate_ranges
+//       Access: Published
+//  Description: Verifies that all of the packed values in the field
+//               data are within the specified ranges and that there
+//               are no extra bytes on the end of the record.  Returns
+//               true if all fields are valid, false otherwise.
+////////////////////////////////////////////////////////////////////
+bool DCField::
+validate_ranges(const string &packed_data) const {
+  DCPacker packer;
+  packer.begin_unpack(packed_data, this);
+  packer.unpack_validate();
+  if (!packer.end_unpack()) {
+    return false;
+  }
+
+  return (packer.get_num_unpacked_bytes() == packed_data.length());
+}
+
 #ifdef HAVE_PYTHON
 ////////////////////////////////////////////////////////////////////
 //     Function: DCField::pack_args
@@ -130,8 +150,13 @@ pack_args(Datagram &datagram, PyObject *sequence) const {
   PyObject *str = PyObject_Str(tuple);
   
   ostringstream strm;
-  strm << "Incorrect arguments or value out of range on field: " << get_name()
-       << PyString_AsString(str);
+  if (packer.had_pack_error()) {
+    strm << "Incorrect arguments to field: " << get_name()
+         << PyString_AsString(str);
+  } else {
+    strm << "Value out of range on field: " << get_name()
+         << PyString_AsString(str);
+  }
 
   Py_DECREF(str);
   Py_DECREF(tuple);
@@ -172,7 +197,14 @@ unpack_args(DatagramIterator &iterator) const {
   }
   
   ostringstream strm;
-  strm << "Error unpacking field " << get_name();
+  if (packer.had_pack_error()) {
+    strm << "Error unpacking to field " << get_name();
+  } else {
+    PyObject *str = PyObject_Str(object);
+    strm << "Found value outside specified range when unpacking field " 
+         << get_name() << ": " << PyString_AsString(str);
+    Py_DECREF(str);
+  }
     
   nassert_raise(strm.str());
   return object;

+ 3 - 1
direct/src/dcparser/dcField.h

@@ -52,6 +52,8 @@ PUBLISHED:
   string format_data(const string &packed_data);
   string parse_string(const string &formatted_string);
 
+  bool validate_ranges(const string &packed_data) const;
+
 #ifdef HAVE_PYTHON
   bool pack_args(Datagram &datagram, PyObject *sequence) const;
   PyObject *unpack_args(DatagramIterator &iterator) const;
@@ -66,7 +68,7 @@ public:
   DCField(const string &name);
   virtual ~DCField();
   virtual void write(ostream &out, bool brief, int indent_level) const=0;
-  virtual void generate_hash(HashGenerator &hash) const;
+  virtual void generate_hash(HashGenerator &hashgen) const;
 
   void set_number(int number);
 

+ 1 - 1
direct/src/dcparser/dcFile.h

@@ -66,7 +66,7 @@ PUBLISHED:
   unsigned long get_hash() const;
 
 public:
-  void generate_hash(HashGenerator &hash) const;
+  void generate_hash(HashGenerator &hashgen) const;
   bool add_class(DCClass *dclass);
   void add_import_module(const string &import_module);
   void add_import_symbol(const string &import_symbol);

+ 1 - 1
direct/src/dcparser/dcMolecularField.h

@@ -44,7 +44,7 @@ public:
   void add_atomic(DCAtomicField *atomic);
 
   virtual void write(ostream &out, bool brief, int indent_level) const;
-  virtual void generate_hash(HashGenerator &hash) const;
+  virtual void generate_hash(HashGenerator &hashgen) const;
 
   virtual DCPackerInterface *get_nested_field(int n) const;
 

+ 31 - 0
direct/src/dcparser/dcNumericRange.I

@@ -27,6 +27,17 @@ INLINE DCNumericRange<NUM>::
 DCNumericRange() {
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: DCNumericRange::Constructor
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+template <class NUM>
+INLINE DCNumericRange<NUM>::
+DCNumericRange(Number min, Number max) {
+  add_range(min, max);
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: DCNumericRange::Copy Constructor
 //       Access: Public
@@ -89,6 +100,26 @@ validate(Number num, bool &validation_error) const {
   }
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: DCNumericRange::generate_hash
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+template <class NUM>
+void DCNumericRange<NUM>::
+generate_hash(HashGenerator &hashgen) const {
+  if (!_ranges.empty()) {
+    hashgen.add_int(_ranges.size());
+    TYPENAME Ranges::const_iterator ri;
+    for (ri = _ranges.begin(); ri != _ranges.end(); ++ri) {
+      // We don't account for the fractional part of floating-point
+      // ranges here.  Shouldn't be a real issue.
+      hashgen.add_int((int)(*ri)._min);
+      hashgen.add_int((int)(*ri)._max);
+    }
+  }
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: DCNumericRange::output
 //       Access: Public

+ 4 - 0
direct/src/dcparser/dcNumericRange.h

@@ -20,6 +20,7 @@
 #define DCNUMERICRANGE_H
 
 #include "dcbase.h"
+#include "hashGenerator.h"
 
 ////////////////////////////////////////////////////////////////////
 //       Class : DCNumericRange
@@ -33,12 +34,15 @@ public:
   typedef NUM Number;
 
   INLINE DCNumericRange();
+  INLINE DCNumericRange(Number min, Number max);
   INLINE DCNumericRange(const DCNumericRange &copy);
   INLINE void operator = (const DCNumericRange &copy);
 
   bool is_in_range(Number num) const;
   INLINE void validate(Number num, bool &validation_error) const;
 
+  void generate_hash(HashGenerator &hashgen) const;
+
   void output(ostream &out, Number divisor = 1) const;
 
 public:

+ 47 - 40
direct/src/dcparser/dcPacker.I

@@ -110,9 +110,7 @@ pack_double(double value) {
   if (_current_field == NULL) {
     _pack_error = true;
   } else {
-    if (!_current_field->pack_double(_pack_data, value)) {
-      _pack_error = true;
-    }
+    _current_field->pack_double(_pack_data, value, _pack_error, _range_error);
     advance();
   }
 }
@@ -129,9 +127,7 @@ pack_int(int value) {
   if (_current_field == NULL) {
     _pack_error = true;
   } else {
-    if (!_current_field->pack_int(_pack_data, value)) {
-      _pack_error = true;
-    }
+    _current_field->pack_int(_pack_data, value, _pack_error, _range_error);
     advance();
   }
 }
@@ -148,9 +144,7 @@ pack_uint(unsigned int value) {
   if (_current_field == NULL) {
     _pack_error = true;
   } else {
-    if (!_current_field->pack_uint(_pack_data, value)) {
-      _pack_error = true;
-    }
+    _current_field->pack_uint(_pack_data, value, _pack_error, _range_error);
     advance();
   }
 }
@@ -167,9 +161,7 @@ pack_int64(PN_int64 value) {
   if (_current_field == NULL) {
     _pack_error = true;
   } else {
-    if (!_current_field->pack_int64(_pack_data, value)) {
-      _pack_error = true;
-    }
+    _current_field->pack_int64(_pack_data, value, _pack_error, _range_error);
     advance();
   }
 }
@@ -186,9 +178,7 @@ pack_uint64(PN_uint64 value) {
   if (_current_field == NULL) {
     _pack_error = true;
   } else {
-    if (!_current_field->pack_uint64(_pack_data, value)) {
-      _pack_error = true;
-    }
+    _current_field->pack_uint64(_pack_data, value, _pack_error, _range_error);
     advance();
   }
 }
@@ -205,9 +195,7 @@ pack_string(const string &value) {
   if (_current_field == NULL) {
     _pack_error = true;
   } else {
-    if (!_current_field->pack_string(_pack_data, value)) {
-      _pack_error = true;
-    }
+    _current_field->pack_string(_pack_data, value, _pack_error, _range_error);
     advance();
   }
 }
@@ -244,9 +232,8 @@ unpack_double() {
     _pack_error = true;
 
   } else {
-    if (!_current_field->unpack_double(_unpack_data, _unpack_length, _unpack_p, value)) {
-      _pack_error = true;
-    }
+    _current_field->unpack_double(_unpack_data, _unpack_length, _unpack_p, 
+                                  value, _pack_error, _range_error);
     advance();
   }
 
@@ -267,9 +254,8 @@ unpack_int() {
     _pack_error = true;
 
   } else {
-    if (!_current_field->unpack_int(_unpack_data, _unpack_length, _unpack_p, value)) {
-      _pack_error = true;
-    }
+    _current_field->unpack_int(_unpack_data, _unpack_length, _unpack_p,
+                               value, _pack_error, _range_error);
     advance();
   }
 
@@ -290,9 +276,8 @@ unpack_uint() {
     _pack_error = true;
 
   } else {
-    if (!_current_field->unpack_uint(_unpack_data, _unpack_length, _unpack_p, value)) {
-      _pack_error = true;
-    }
+    _current_field->unpack_uint(_unpack_data, _unpack_length, _unpack_p,
+                                value, _pack_error, _range_error);
     advance();
   }
 
@@ -313,9 +298,8 @@ unpack_int64() {
     _pack_error = true;
 
   } else {
-    if (!_current_field->unpack_int64(_unpack_data, _unpack_length, _unpack_p, value)) {
-      _pack_error = true;
-    }
+    _current_field->unpack_int64(_unpack_data, _unpack_length, _unpack_p,
+                                 value, _pack_error, _range_error);
     advance();
   }
 
@@ -336,9 +320,8 @@ unpack_uint64() {
     _pack_error = true;
 
   } else {
-    if (!_current_field->unpack_uint64(_unpack_data, _unpack_length, _unpack_p, value)) {
-      _pack_error = true;
-    }
+    _current_field->unpack_uint64(_unpack_data, _unpack_length, _unpack_p,
+                                  value, _pack_error, _range_error);
     advance();
   }
 
@@ -359,9 +342,8 @@ unpack_string() {
     _pack_error = true;
 
   } else {
-    if (!_current_field->unpack_string(_unpack_data, _unpack_length, _unpack_p, value)) {
-      _pack_error = true;
-    }
+    _current_field->unpack_string(_unpack_data, _unpack_length, _unpack_p,
+                                  value, _pack_error, _range_error);
     advance();
   }
 
@@ -386,16 +368,41 @@ unpack_literal_value() {
 ////////////////////////////////////////////////////////////////////
 //     Function: DCPacker::had_pack_error
 //       Access: Published
-//  Description: Returns true if there has been an error in packing
-//               since the most recent call to begin().  It is
-//               most useful to call this after end() to validate
-//               the entire packing run.
+//  Description: Returns true if there has been an packing error
+//               since the most recent call to begin(); in particular,
+//               this may be called after end() has returned false to
+//               determine the nature of the failure.
+//
+//               A return value of true indicates there was a push/pop
+//               mismatch, or the push/pop structure did not match the
+//               data structure, or there were the wrong number of
+//               elements in a nested push/pop structure, or on unpack
+//               that the data stream was truncated.
 ////////////////////////////////////////////////////////////////////
 INLINE bool DCPacker::
 had_pack_error() const {
   return _pack_error;
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: DCPacker::had_range_error
+//       Access: Published
+//  Description: Returns true if there has been an range validation
+//               error since the most recent call to begin(); in
+//               particular, this may be called after end() has
+//               returned false to determine the nature of the
+//               failure.
+//
+//               A return value of true indicates a value that was
+//               packed or unpacked did not fit within the specified
+//               legal range for a parameter, or within the limits of
+//               the field size.
+////////////////////////////////////////////////////////////////////
+INLINE bool DCPacker::
+had_range_error() const {
+  return _range_error;
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: DCPacker::get_num_unpacked_bytes
 //       Access: Published

+ 43 - 10
direct/src/dcparser/dcPacker.cxx

@@ -40,6 +40,7 @@ DCPacker() {
   _current_field_index = 0;
   _num_nested_fields = 0;
   _pack_error = false;
+  _range_error = false;
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -65,6 +66,7 @@ begin_pack(const DCPackerInterface *root) {
   
   _mode = M_pack;
   _pack_error = false;
+  _range_error = false;
   _pack_data.clear();
 
   _root = root;
@@ -97,7 +99,7 @@ end_pack() {
 
   clear();
 
-  return !_pack_error;
+  return !_pack_error && !_range_error;
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -128,6 +130,7 @@ begin_unpack(const char *data, size_t length,
   
   _mode = M_unpack;
   _pack_error = false;
+  _range_error = false;
   set_unpack_data(data, length, false);
   _unpack_p = 0;
 
@@ -170,7 +173,7 @@ end_unpack() {
 
   clear();
 
-  return !_pack_error;
+  return !_pack_error && !_range_error;
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -208,6 +211,7 @@ begin_repack(const char *data, size_t length,
   
   _mode = M_repack;
   _pack_error = false;
+  _range_error = false;
   set_unpack_data(data, length, false);
   _unpack_p = 0;
 
@@ -244,7 +248,7 @@ end_repack() {
   _mode = M_idle;
   clear();
 
-  return !_pack_error;
+  return !_pack_error && !_range_error;
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -429,7 +433,6 @@ push() {
     } else {
       _current_field = _current_parent->get_nested_field(_current_field_index);
     }
-
   }
 }
 
@@ -467,12 +470,11 @@ pop() {
         size_t length = _pack_data.get_length() - _push_marker - length_bytes;
         if (length_bytes == 4) {
           DCPackerInterface::do_pack_uint32
-            (_pack_data.get_rewrite_pointer(_push_marker, 4), length, 
-             _pack_error);
+            (_pack_data.get_rewrite_pointer(_push_marker, 4), length);
         } else {
+          DCPackerInterface::validate_uint_limits(length, 16, _range_error);
           DCPackerInterface::do_pack_uint16
-            (_pack_data.get_rewrite_pointer(_push_marker, 2), length,
-             _pack_error);
+            (_pack_data.get_rewrite_pointer(_push_marker, 2), length);
         }
       }
     }
@@ -488,13 +490,44 @@ pop() {
   advance();
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: DCPacker::unpack_validate
+//       Access: Published
+//  Description: Internally unpacks the current numeric or string
+//               value and validates it against the type range limits,
+//               but does not return the value.  If the current field
+//               contains nested fields, validates all of them.
+////////////////////////////////////////////////////////////////////
+void DCPacker::
+unpack_validate() {
+  nassertv(_mode == M_unpack);
+  if (_current_field == NULL) {
+    _pack_error = true;
+
+  } else {
+    if (_current_field->unpack_validate(_unpack_data, _unpack_length, _unpack_p,
+                                        _pack_error, _range_error)) {
+      advance();
+    } else {
+      // If the single field couldn't be validated, try validating
+      // nested fields.
+      push();
+      while (more_nested_fields()) {
+        unpack_validate();
+      }
+      pop();
+    }
+  }
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: DCPacker::unpack_skip
 //       Access: Published
 //  Description: Skips the current field without unpacking it and
-//               advances to the next field.
+//               advances to the next field.  If the current field
+//               contains nested fields, skips all of them.
 ////////////////////////////////////////////////////////////////////
-INLINE void DCPacker::
+void DCPacker::
 unpack_skip() {
   nassertv(_mode == M_unpack);
   if (_current_field == NULL) {

+ 3 - 0
direct/src/dcparser/dcPacker.h

@@ -80,6 +80,7 @@ PUBLISHED:
   INLINE PN_uint64 unpack_uint64();
   INLINE string unpack_string();
   INLINE string unpack_literal_value();
+  INLINE void unpack_validate();
   void unpack_skip();
 
 #ifdef HAVE_PYTHON
@@ -93,6 +94,7 @@ PUBLISHED:
   void unpack_and_format(ostream &out);
 
   INLINE bool had_pack_error() const;
+  INLINE bool had_range_error() const;
   INLINE size_t get_num_unpacked_bytes() const;
 
   INLINE string get_string() const;
@@ -147,6 +149,7 @@ private:
   int _num_nested_fields;
 
   bool _pack_error;
+  bool _range_error;
 };
 
 #include "dcPacker.I"

+ 82 - 21
direct/src/dcparser/dcPackerInterface.I

@@ -117,11 +117,8 @@ get_pack_type() const {
 //  Description: 
 ////////////////////////////////////////////////////////////////////
 INLINE void DCPackerInterface::
-do_pack_int8(char *buffer, int value, bool &pack_error) {
+do_pack_int8(char *buffer, int value) {
   buffer[0] = (char)(value & 0xff);
-  if ((abs(value) & ~0xff) != 0) {
-    pack_error = true;
-  }
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -130,12 +127,9 @@ do_pack_int8(char *buffer, int value, bool &pack_error) {
 //  Description: 
 ////////////////////////////////////////////////////////////////////
 INLINE void DCPackerInterface::
-do_pack_int16(char *buffer, int value, bool &pack_error) {
+do_pack_int16(char *buffer, int value) {
   buffer[0] = (char)(value & 0xff);
   buffer[1] = (char)((value >> 8) & 0xff);
-  if ((abs(value) & ~0xffff) != 0) {
-    pack_error = true;
-  }
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -144,7 +138,7 @@ do_pack_int16(char *buffer, int value, bool &pack_error) {
 //  Description: 
 ////////////////////////////////////////////////////////////////////
 INLINE void DCPackerInterface::
-do_pack_int32(char *buffer, int value, bool &) {
+do_pack_int32(char *buffer, int value) {
   buffer[0] = (char)(value & 0xff);
   buffer[1] = (char)((value >> 8) & 0xff);
   buffer[2] = (char)((value >> 16) & 0xff);
@@ -157,7 +151,7 @@ do_pack_int32(char *buffer, int value, bool &) {
 //  Description: 
 ////////////////////////////////////////////////////////////////////
 INLINE void DCPackerInterface::
-do_pack_int64(char *buffer, PN_int64 value, bool &) {
+do_pack_int64(char *buffer, PN_int64 value) {
   buffer[0] = (char)(value & 0xff);
   buffer[1] = (char)((value >> 8) & 0xff);
   buffer[2] = (char)((value >> 16) & 0xff);
@@ -174,11 +168,8 @@ do_pack_int64(char *buffer, PN_int64 value, bool &) {
 //  Description: 
 ////////////////////////////////////////////////////////////////////
 INLINE void DCPackerInterface::
-do_pack_uint8(char *buffer, unsigned int value, bool &pack_error) {
+do_pack_uint8(char *buffer, unsigned int value) {
   buffer[0] = (char)(value & 0xff);
-  if ((value & ~0xff) != 0) {
-    pack_error = true;
-  }
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -187,12 +178,9 @@ do_pack_uint8(char *buffer, unsigned int value, bool &pack_error) {
 //  Description: 
 ////////////////////////////////////////////////////////////////////
 INLINE void DCPackerInterface::
-do_pack_uint16(char *buffer, unsigned int value, bool &pack_error) {
+do_pack_uint16(char *buffer, unsigned int value) {
   buffer[0] = (char)(value & 0xff);
   buffer[1] = (char)((value >> 8) & 0xff);
-  if ((value & ~0xffff) != 0) {
-    pack_error = true;
-  }
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -201,7 +189,7 @@ do_pack_uint16(char *buffer, unsigned int value, bool &pack_error) {
 //  Description: 
 ////////////////////////////////////////////////////////////////////
 INLINE void DCPackerInterface::
-do_pack_uint32(char *buffer, unsigned int value, bool &) {
+do_pack_uint32(char *buffer, unsigned int value) {
   buffer[0] = (char)(value & 0xff);
   buffer[1] = (char)((value >> 8) & 0xff);
   buffer[2] = (char)((value >> 16) & 0xff);
@@ -214,7 +202,7 @@ do_pack_uint32(char *buffer, unsigned int value, bool &) {
 //  Description: 
 ////////////////////////////////////////////////////////////////////
 INLINE void DCPackerInterface::
-do_pack_uint64(char *buffer, PN_uint64 value, bool &) {
+do_pack_uint64(char *buffer, PN_uint64 value) {
   buffer[0] = (char)(value & 0xff);
   buffer[1] = (char)((value >> 8) & 0xff);
   buffer[2] = (char)((value >> 16) & 0xff);
@@ -231,7 +219,7 @@ do_pack_uint64(char *buffer, PN_uint64 value, bool &) {
 //  Description: 
 ////////////////////////////////////////////////////////////////////
 INLINE void DCPackerInterface::
-do_pack_float64(char *buffer, double value, bool &) {
+do_pack_float64(char *buffer, double value) {
 #ifdef WORDS_BIGENDIAN
   // Reverse the byte ordering for big-endian machines.
   char *p = (char *)value;
@@ -365,3 +353,76 @@ do_unpack_float64(const char *buffer) {
   return *(double *)buffer;
 #endif  // WORDS_BIGENDIAN 
 }
+
+////////////////////////////////////////////////////////////////////
+//     Function: DCPackerInterface::validate_int_limits
+//       Access: Public, Static
+//  Description: Confirms that the signed value fits within num_bits
+//               bits.  Sets range_error true if it does not.
+////////////////////////////////////////////////////////////////////
+INLINE void DCPackerInterface::
+validate_int_limits(int value, int num_bits, bool &range_error) {
+  // What we're really checking is that all of the bits above the
+  // lower (num_bits - 1) bits are the same--either all 1 or all 0.
+
+  // First, turn on the lower (num_bits - 1).
+  int mask = ((int)1 << (num_bits - 1)) - 1;
+  value |= mask;
+
+  // The result should be either mask (all high bits are 0) or -1 (all
+  // high bits are 1).  If it is anything else we have a range error.
+  if (value != mask && value != -1) {
+    range_error = true;
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: DCPackerInterface::validate_int64_limits
+//       Access: Public, Static
+//  Description: Confirms that the signed value fits within num_bits
+//               bits.  Sets range_error true if it does not.
+////////////////////////////////////////////////////////////////////
+INLINE void DCPackerInterface::
+validate_int64_limits(PN_int64 value, int num_bits, bool &range_error) {
+  PN_int64 mask = ((PN_int64)1 << (num_bits - 1)) - 1;
+  value |= mask;
+
+  if (value != mask && value != -1) {
+    range_error = true;
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: DCPackerInterface::validate_uint_limits
+//       Access: Public, Static
+//  Description: Confirms that the unsigned value fits within num_bits
+//               bits.  Sets range_error true if it does not.
+////////////////////////////////////////////////////////////////////
+INLINE void DCPackerInterface::
+validate_uint_limits(unsigned int value, int num_bits, bool &range_error) {
+  // Here we're really checking that all of the bits above the lower
+  // num_bits bits are all 0.
+
+  unsigned int mask = ((unsigned int)1 << num_bits) - 1;
+  value &= ~mask;
+
+  if (value != 0) {
+    range_error = true;
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: DCPackerInterface::validate_uint64_limits
+//       Access: Public, Static
+//  Description: Confirms that the unsigned value fits within num_bits
+//               bits.  Sets range_error true if it does not.
+////////////////////////////////////////////////////////////////////
+INLINE void DCPackerInterface::
+validate_uint64_limits(PN_uint64 value, int num_bits, bool &range_error) {
+  PN_uint64 mask = ((PN_uint64)1 << num_bits) - 1;
+  value &= ~mask;
+
+  if (value != 0) {
+    range_error = true;
+  }
+}

+ 63 - 48
direct/src/dcparser/dcPackerInterface.cxx

@@ -99,131 +99,145 @@ get_nested_field(int n) const {
 //     Function: DCPackerInterface::pack_double
 //       Access: Public, Virtual
 //  Description: Packs the indicated numeric or string value into the
-//               stream.  Returns true on success, false on failure.
+//               stream.
 ////////////////////////////////////////////////////////////////////
-bool DCPackerInterface::
-pack_double(DCPackData &, double) const {
-  return false;
+void DCPackerInterface::
+pack_double(DCPackData &, double, bool &pack_error, bool &) const {
+  pack_error = true;
 }
 
 ////////////////////////////////////////////////////////////////////
 //     Function: DCPackerInterface::pack_int
 //       Access: Public, Virtual
 //  Description: Packs the indicated numeric or string value into the
-//               stream.  Returns true on success, false on failure.
+//               stream.
 ////////////////////////////////////////////////////////////////////
-bool DCPackerInterface::
-pack_int(DCPackData &, int) const {
-  return false;
+void DCPackerInterface::
+pack_int(DCPackData &, int, bool &pack_error, bool &) const {
+  pack_error = true;
 }
 
 ////////////////////////////////////////////////////////////////////
 //     Function: DCPackerInterface::pack_uint
 //       Access: Public, Virtual
 //  Description: Packs the indicated numeric or string value into the
-//               stream.  Returns true on success, false on failure.
+//               stream.
 ////////////////////////////////////////////////////////////////////
-bool DCPackerInterface::
-pack_uint(DCPackData &, unsigned int) const {
-  return false;
+void DCPackerInterface::
+pack_uint(DCPackData &, unsigned int, bool &pack_error, bool &) const {
+  pack_error = true;
 }
 
 ////////////////////////////////////////////////////////////////////
 //     Function: DCPackerInterface::pack_int64
 //       Access: Public, Virtual
 //  Description: Packs the indicated numeric or string value into the
-//               stream.  Returns true on success, false on failure.
+//               stream.
 ////////////////////////////////////////////////////////////////////
-bool DCPackerInterface::
-pack_int64(DCPackData &, PN_int64) const {
-  return false;
+void DCPackerInterface::
+pack_int64(DCPackData &, PN_int64, bool &pack_error, bool &) const {
+  pack_error = true;
 }
 
 ////////////////////////////////////////////////////////////////////
 //     Function: DCPackerInterface::pack_uint64
 //       Access: Public, Virtual
 //  Description: Packs the indicated numeric or string value into the
-//               stream.  Returns true on success, false on failure.
+//               stream.
 ////////////////////////////////////////////////////////////////////
-bool DCPackerInterface::
-pack_uint64(DCPackData &, PN_uint64) const {
-  return false;
+void DCPackerInterface::
+pack_uint64(DCPackData &, PN_uint64, bool &pack_error, bool &) const {
+  pack_error = true;
 }
 
 ////////////////////////////////////////////////////////////////////
 //     Function: DCPackerInterface::pack_string
 //       Access: Public, Virtual
 //  Description: Packs the indicated numeric or string value into the
-//               stream.  Returns true on success, false on failure.
+//               stream.
 ////////////////////////////////////////////////////////////////////
-bool DCPackerInterface::
-pack_string(DCPackData &, const string &) const {
-  return false;
+void DCPackerInterface::
+pack_string(DCPackData &, const string &, bool &pack_error, bool &) const {
+  pack_error = true;
 }
 
 ////////////////////////////////////////////////////////////////////
 //     Function: DCPackerInterface::unpack_double
 //       Access: Public, Virtual
 //  Description: Unpacks the current numeric or string value from the
-//               stream.  Returns true on success, false on failure.
+//               stream.
 ////////////////////////////////////////////////////////////////////
-bool DCPackerInterface::
-unpack_double(const char *, size_t, size_t &, double &) const {
-  return false;
+void DCPackerInterface::
+unpack_double(const char *, size_t, size_t &, double &, bool &pack_error, bool &) const {
+  pack_error = true;
 }
 
 ////////////////////////////////////////////////////////////////////
 //     Function: DCPackerInterface::unpack_int
 //       Access: Public, Virtual
 //  Description: Unpacks the current numeric or string value from the
-//               stream.  Returns true on success, false on failure.
+//               stream.
 ////////////////////////////////////////////////////////////////////
-bool DCPackerInterface::
-unpack_int(const char *, size_t, size_t &, int &) const {
-  return false;
+void DCPackerInterface::
+unpack_int(const char *, size_t, size_t &, int &, bool &pack_error, bool &) const {
+  pack_error = true;
 }
 
 ////////////////////////////////////////////////////////////////////
 //     Function: DCPackerInterface::unpack_uint
 //       Access: Public, Virtual
 //  Description: Unpacks the current numeric or string value from the
-//               stream.  Returns true on success, false on failure.
+//               stream.
 ////////////////////////////////////////////////////////////////////
-bool DCPackerInterface::
-unpack_uint(const char *, size_t, size_t &, unsigned int &) const {
-  return false;
+void DCPackerInterface::
+unpack_uint(const char *, size_t, size_t &, unsigned int &, bool &pack_error, bool &) const {
+  pack_error = true;
 }
 
 ////////////////////////////////////////////////////////////////////
 //     Function: DCPackerInterface::unpack_int64
 //       Access: Public, Virtual
 //  Description: Unpacks the current numeric or string value from the
-//               stream.  Returns true on success, false on failure.
+//               stream.
 ////////////////////////////////////////////////////////////////////
-bool DCPackerInterface::
-unpack_int64(const char *, size_t, size_t &, PN_int64 &) const {
-  return false;
+void DCPackerInterface::
+unpack_int64(const char *, size_t, size_t &, PN_int64 &, bool &pack_error, bool &) const {
+  pack_error = true;
 }
 
 ////////////////////////////////////////////////////////////////////
 //     Function: DCPackerInterface::unpack_uint64
 //       Access: Public, Virtual
 //  Description: Unpacks the current numeric or string value from the
-//               stream.  Returns true on success, false on failure.
+//               stream.
 ////////////////////////////////////////////////////////////////////
-bool DCPackerInterface::
-unpack_uint64(const char *, size_t, size_t &, PN_uint64 &) const {
-  return false;
+void DCPackerInterface::
+unpack_uint64(const char *, size_t, size_t &, PN_uint64 &, bool &pack_error, bool &) const {
+  pack_error = true;
 }
 
 ////////////////////////////////////////////////////////////////////
 //     Function: DCPackerInterface::unpack_string
 //       Access: Public, Virtual
 //  Description: Unpacks the current numeric or string value from the
-//               stream.  Returns true on success, false on failure.
+//               stream.
+////////////////////////////////////////////////////////////////////
+void DCPackerInterface::
+unpack_string(const char *, size_t, size_t &, string &, bool &pack_error, bool &) const {
+  pack_error = true;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: DCPackerInterface::unpack_validate
+//       Access: Public, Virtual
+//  Description: Internally unpacks the current numeric or string
+//               value and validates it against the type range limits,
+//               but does not return the value.  Returns true on
+//               success, false on failure (e.g. we don't know how to
+//               validate this field).
 ////////////////////////////////////////////////////////////////////
 bool DCPackerInterface::
-unpack_string(const char *, size_t, size_t &, string &) const {
+unpack_validate(const char *, size_t, size_t &, bool &, bool &) const {
   return false;
 }
 
@@ -231,8 +245,9 @@ unpack_string(const char *, size_t, size_t &, string &) const {
 //     Function: DCPackerInterface::unpack_skip
 //       Access: Public, Virtual
 //  Description: Increments p to the end of the current field without
-//               actually unpacking any data.  Returns true on
-//               success, false on failure.
+//               actually unpacking any data or performing any range
+//               validation.  Returns true on success, false on
+//               failure (e.g. we don't know how to skip this field).
 ////////////////////////////////////////////////////////////////////
 bool DCPackerInterface::
 unpack_skip(const char *, size_t, size_t &) const {

+ 45 - 22
direct/src/dcparser/dcPackerInterface.h

@@ -83,33 +83,47 @@ public:
 
   INLINE DCPackType get_pack_type() const;
 
-  virtual bool pack_double(DCPackData &pack_data, double value) const;
-  virtual bool pack_int(DCPackData &pack_data, int value) const;
-  virtual bool pack_uint(DCPackData &pack_data, unsigned int value) const;
-  virtual bool pack_int64(DCPackData &pack_data, PN_int64 value) const;
-  virtual bool pack_uint64(DCPackData &pack_data, PN_uint64 value) const;
-  virtual bool pack_string(DCPackData &pack_data, const string &value) const;
-
-  virtual bool unpack_double(const char *data, size_t length, size_t &p, double &value) const;
-  virtual bool unpack_int(const char *data, size_t length, size_t &p, int &value) const;
-  virtual bool unpack_uint(const char *data, size_t length, size_t &p, unsigned int &value) const;
-  virtual bool unpack_int64(const char *data, size_t length, size_t &p, PN_int64 &value) const;
-  virtual bool unpack_uint64(const char *data, size_t length, size_t &p, PN_uint64 &value) const;
-  virtual bool unpack_string(const char *data, size_t length, size_t &p, string &value) const;
+  virtual void pack_double(DCPackData &pack_data, double value,
+                           bool &pack_error, bool &range_error) const;
+  virtual void pack_int(DCPackData &pack_data, int value,
+                        bool &pack_error, bool &range_error) const;
+  virtual void pack_uint(DCPackData &pack_data, unsigned int value,
+                         bool &pack_error, bool &range_error) const;
+  virtual void pack_int64(DCPackData &pack_data, PN_int64 value,
+                          bool &pack_error, bool &range_error) const;
+  virtual void pack_uint64(DCPackData &pack_data, PN_uint64 value,
+                           bool &pack_error, bool &range_error) const;
+  virtual void pack_string(DCPackData &pack_data, const string &value,
+                           bool &pack_error, bool &range_error) const;
+
+  virtual void unpack_double(const char *data, size_t length, size_t &p, 
+                             double &value, bool &pack_error, bool &range_error) const;
+  virtual void unpack_int(const char *data, size_t length, size_t &p, 
+                          int &value, bool &pack_error, bool &range_error) const;
+  virtual void unpack_uint(const char *data, size_t length, size_t &p, 
+                           unsigned int &value, bool &pack_error, bool &range_error) const;
+  virtual void unpack_int64(const char *data, size_t length, size_t &p, 
+                            PN_int64 &value, bool &pack_error, bool &range_error) const;
+  virtual void unpack_uint64(const char *data, size_t length, size_t &p, 
+                             PN_uint64 &value, bool &pack_error, bool &range_error) const;
+  virtual void unpack_string(const char *data, size_t length, size_t &p, 
+                             string &value, bool &pack_error, bool &range_error) const;
+  virtual bool unpack_validate(const char *data, size_t length, size_t &p, 
+                               bool &pack_error, bool &range_error) const;
   virtual bool unpack_skip(const char *data, size_t length, size_t &p) const;
 
   // These are the low-level interfaces for packing and unpacking
   // numbers from a buffer.  You're responsible for making sure the
   // buffer has enough room, and for incrementing the pointer.
-  INLINE static void do_pack_int8(char *buffer, int value, bool &pack_error);
-  INLINE static void do_pack_int16(char *buffer, int value, bool &pack_error);
-  INLINE static void do_pack_int32(char *buffer, int value, bool &pack_error);
-  INLINE static void do_pack_int64(char *buffer, PN_int64 value, bool &pack_error);
-  INLINE static void do_pack_uint8(char *buffer, unsigned int value, bool &pack_error);
-  INLINE static void do_pack_uint16(char *buffer, unsigned int value, bool &pack_error);
-  INLINE static void do_pack_uint32(char *buffer, unsigned int value, bool &pack_error);
-  INLINE static void do_pack_uint64(char *buffer, PN_uint64 value, bool &pack_error);
-  INLINE static void do_pack_float64(char *buffer, double value, bool &pack_error);
+  INLINE static void do_pack_int8(char *buffer, int value);
+  INLINE static void do_pack_int16(char *buffer, int value);
+  INLINE static void do_pack_int32(char *buffer, int value);
+  INLINE static void do_pack_int64(char *buffer, PN_int64 value);
+  INLINE static void do_pack_uint8(char *buffer, unsigned int value);
+  INLINE static void do_pack_uint16(char *buffer, unsigned int value);
+  INLINE static void do_pack_uint32(char *buffer, unsigned int value);
+  INLINE static void do_pack_uint64(char *buffer, PN_uint64 value);
+  INLINE static void do_pack_float64(char *buffer, double value);
 
   INLINE static int do_unpack_int8(const char *buffer);
   INLINE static int do_unpack_int16(const char *buffer);
@@ -121,6 +135,15 @@ public:
   INLINE static PN_uint64 do_unpack_uint64(const char *buffer);
   INLINE static double do_unpack_float64(const char *buffer);
 
+  INLINE static void validate_int_limits(int value, int num_bits, 
+                                         bool &range_error);
+  INLINE static void validate_int64_limits(PN_int64 value, int num_bits, 
+                                           bool &range_error);
+  INLINE static void validate_uint_limits(unsigned int value, int num_bits, 
+                                          bool &range_error);
+  INLINE static void validate_uint64_limits(PN_uint64 value, int num_bits, 
+                                            bool &range_error);
+
   const DCPackerCatalog *get_catalog() const;
 
 protected:

+ 1 - 1
direct/src/dcparser/dcParameter.h

@@ -65,7 +65,7 @@ public:
                                const string &name, const string &postname) const=0;
   void output_typedef_name(ostream &out, const string &prename, 
                            const string &name, const string &postname) const;
-  virtual void generate_hash(HashGenerator &hash) const;
+  virtual void generate_hash(HashGenerator &hashgen) const;
 
 private:
   const DCTypedef *_typedef;

+ 80 - 74
direct/src/dcparser/dcParser.cxx.prebuilt

@@ -224,14 +224,14 @@ static const short yyrline[] =
      207,   209,   215,   220,   226,   242,   244,   247,   254,   262,
      264,   265,   266,   267,   271,   279,   279,   290,   306,   308,
      311,   313,   316,   322,   322,   346,   346,   357,   361,   363,
-     366,   371,   377,   388,   400,   412,   433,   438,   445,   452,
-     462,   468,   474,   485,   487,   491,   497,   503,   517,   521,
-     527,   532,   535,   540,   544,   548,   552,   552,   560,   560,
-     568,   568,   576,   582,   588,   596,   598,   601,   603,   606,
-     608,   611,   616,   620,   624,   628,   632,   636,   640,   644,
-     648,   652,   656,   660,   664,   668,   672,   676,   680,   684,
-     690,   692,   696,   700,   704,   708,   712,   716,   720,   724,
-     730,   730,   741,   748,   761
+     366,   371,   379,   390,   404,   418,   439,   444,   451,   458,
+     468,   474,   480,   491,   493,   497,   503,   509,   523,   527,
+     533,   538,   541,   546,   550,   554,   558,   558,   566,   566,
+     574,   574,   582,   588,   594,   602,   604,   607,   609,   612,
+     614,   617,   622,   626,   630,   634,   638,   642,   646,   650,
+     654,   658,   662,   666,   670,   674,   678,   682,   686,   690,
+     696,   698,   702,   706,   710,   714,   718,   722,   726,   730,
+     736,   736,   747,   754,   767
 };
 #endif
 
@@ -1321,12 +1321,14 @@ case 51:
 #line 372 "dcParser.yxx"
 {
   DCSimpleParameter *simple_param = new DCSimpleParameter(yyvsp[-3].u.subatomic);
-  simple_param->set_range(double_range);
+  if (!simple_param->set_range(double_range)) {
+    yyerror("Inappropriate range for type");
+  }
   yyval.u.parameter = simple_param;
 }
     break;
 case 52:
-#line 378 "dcParser.yxx"
+#line 380 "dcParser.yxx"
 {
   DCSimpleParameter *simple_param = new DCSimpleParameter(yyvsp[-2].u.subatomic);
   if (yyvsp[0].u.integer == 0) {
@@ -1339,7 +1341,7 @@ case 52:
 }
     break;
 case 53:
-#line 389 "dcParser.yxx"
+#line 391 "dcParser.yxx"
 {
   DCSimpleParameter *simple_param = new DCSimpleParameter(yyvsp[-5].u.subatomic);
   if (yyvsp[-3].u.integer == 0) {
@@ -1348,12 +1350,14 @@ case 53:
   } else if (!simple_param->set_divisor(yyvsp[-3].u.integer)) {
     yyerror("A divisor is only valid on a numeric type.");
   }
-  simple_param->set_range(double_range);
+  if (!simple_param->set_range(double_range)) {
+    yyerror("Inappropriate range for type");
+  }
   yyval.u.parameter = simple_param;
 }
     break;
 case 54:
-#line 401 "dcParser.yxx"
+#line 405 "dcParser.yxx"
 {
   DCSimpleParameter *simple_param = new DCSimpleParameter(yyvsp[-5].u.subatomic);
   if (yyvsp[0].u.integer == 0) {
@@ -1362,12 +1366,14 @@ case 54:
   } else if (!simple_param->set_divisor(yyvsp[0].u.integer)) {
     yyerror("A divisor is only valid on a numeric type.");
   }
-  simple_param->set_range(double_range);
+  if (!simple_param->set_range(double_range)) {
+    yyerror("Inappropriate range for type");
+  }
   yyval.u.parameter = simple_param;
 }
     break;
 case 55:
-#line 413 "dcParser.yxx"
+#line 419 "dcParser.yxx"
 {
   DCTypedef *dtypedef = dc_file->get_typedef_by_name(yyvsp[0].str);
   if (dtypedef == (DCTypedef *)NULL) {
@@ -1388,13 +1394,13 @@ case 55:
 }
     break;
 case 56:
-#line 435 "dcParser.yxx"
+#line 441 "dcParser.yxx"
 {
   double_range.clear();
 }
     break;
 case 57:
-#line 439 "dcParser.yxx"
+#line 445 "dcParser.yxx"
 {
   double_range.clear();
   if (!double_range.add_range(yyvsp[0].u.real, yyvsp[0].u.real)) {
@@ -1403,7 +1409,7 @@ case 57:
 }
     break;
 case 58:
-#line 446 "dcParser.yxx"
+#line 452 "dcParser.yxx"
 {
   double_range.clear();
   if (!double_range.add_range(yyvsp[-2].u.real, yyvsp[0].u.real)) {
@@ -1412,7 +1418,7 @@ case 58:
 }
     break;
 case 59:
-#line 453 "dcParser.yxx"
+#line 459 "dcParser.yxx"
 {
   double_range.clear();
   if (yyvsp[0].u.real >= 0) {
@@ -1424,7 +1430,7 @@ case 59:
 }
     break;
 case 60:
-#line 463 "dcParser.yxx"
+#line 469 "dcParser.yxx"
 {
   if (!double_range.add_range(yyvsp[0].u.real, yyvsp[0].u.real)) {
     yyerror("Overlapping range");
@@ -1432,7 +1438,7 @@ case 60:
 }
     break;
 case 61:
-#line 469 "dcParser.yxx"
+#line 475 "dcParser.yxx"
 {
   if (!double_range.add_range(yyvsp[-2].u.real, yyvsp[0].u.real)) {
     yyerror("Overlapping range");
@@ -1440,7 +1446,7 @@ case 61:
 }
     break;
 case 62:
-#line 475 "dcParser.yxx"
+#line 481 "dcParser.yxx"
 {
   if (yyvsp[0].u.real >= 0) {
     yyerror("Syntax error");
@@ -1451,26 +1457,26 @@ case 62:
 }
     break;
 case 64:
-#line 488 "dcParser.yxx"
+#line 494 "dcParser.yxx"
 {
   yyval.u.parameter = new DCArrayParameter(yyvsp[-2].u.parameter);
 }
     break;
 case 65:
-#line 492 "dcParser.yxx"
+#line 498 "dcParser.yxx"
 {
   yyval.u.parameter = new DCArrayParameter(yyvsp[-3].u.parameter, yyvsp[-1].u.integer);
 }
     break;
 case 66:
-#line 499 "dcParser.yxx"
+#line 505 "dcParser.yxx"
 {
   current_parameter->set_name(yyvsp[0].str);
   yyval.u.parameter = current_parameter;
 }
     break;
 case 67:
-#line 504 "dcParser.yxx"
+#line 510 "dcParser.yxx"
 {
   if (yyvsp[0].u.integer == 0) {
     yyerror("Invalid divisor.");
@@ -1486,85 +1492,85 @@ case 67:
 }
     break;
 case 68:
-#line 518 "dcParser.yxx"
+#line 524 "dcParser.yxx"
 {
   yyval.u.parameter = new DCArrayParameter(yyvsp[-2].u.parameter);
 }
     break;
 case 69:
-#line 522 "dcParser.yxx"
+#line 528 "dcParser.yxx"
 {
   yyval.u.parameter = new DCArrayParameter(yyvsp[-3].u.parameter, yyvsp[-1].u.integer);
 }
     break;
 case 70:
-#line 529 "dcParser.yxx"
+#line 535 "dcParser.yxx"
 {
   yyval.u.real = (double)yyvsp[0].u.integer;
 }
     break;
 case 72:
-#line 537 "dcParser.yxx"
+#line 543 "dcParser.yxx"
 {
   current_packer->pack_int64(yyvsp[0].u.integer);
 }
     break;
 case 73:
-#line 541 "dcParser.yxx"
+#line 547 "dcParser.yxx"
 {
   current_packer->pack_double(yyvsp[0].u.real);
 }
     break;
 case 74:
-#line 545 "dcParser.yxx"
+#line 551 "dcParser.yxx"
 {
   current_packer->pack_string(yyvsp[0].str);
 }
     break;
 case 75:
-#line 549 "dcParser.yxx"
+#line 555 "dcParser.yxx"
 {
   current_packer->pack_literal_value(yyvsp[0].str);
 }
     break;
 case 76:
-#line 553 "dcParser.yxx"
+#line 559 "dcParser.yxx"
 {
   current_packer->push();
 }
     break;
 case 77:
-#line 557 "dcParser.yxx"
+#line 563 "dcParser.yxx"
 {
   current_packer->pop();
 }
     break;
 case 78:
-#line 561 "dcParser.yxx"
+#line 567 "dcParser.yxx"
 {
   current_packer->push();
 }
     break;
 case 79:
-#line 565 "dcParser.yxx"
+#line 571 "dcParser.yxx"
 {
   current_packer->pop();
 }
     break;
 case 80:
-#line 569 "dcParser.yxx"
+#line 575 "dcParser.yxx"
 {
   current_packer->push();
 }
     break;
 case 81:
-#line 573 "dcParser.yxx"
+#line 579 "dcParser.yxx"
 {
   current_packer->pop();
 }
     break;
 case 82:
-#line 577 "dcParser.yxx"
+#line 583 "dcParser.yxx"
 {
   for (int i = 0; i < yyvsp[0].u.integer; i++) {
     current_packer->pack_int64(yyvsp[-2].u.integer);
@@ -1572,7 +1578,7 @@ case 82:
 }
     break;
 case 83:
-#line 583 "dcParser.yxx"
+#line 589 "dcParser.yxx"
 {
   for (int i = 0; i < yyvsp[0].u.integer; i++) {
     current_packer->pack_double(yyvsp[-2].u.real);
@@ -1580,7 +1586,7 @@ case 83:
 }
     break;
 case 84:
-#line 589 "dcParser.yxx"
+#line 595 "dcParser.yxx"
 {
   for (int i = 0; i < yyvsp[0].u.integer; i++) {
     current_packer->pack_literal_value(yyvsp[-2].str);
@@ -1588,175 +1594,175 @@ case 84:
 }
     break;
 case 91:
-#line 613 "dcParser.yxx"
+#line 619 "dcParser.yxx"
 {
   yyval.u.subatomic = ST_int8;
 }
     break;
 case 92:
-#line 617 "dcParser.yxx"
+#line 623 "dcParser.yxx"
 {
   yyval.u.subatomic = ST_int16;
 }
     break;
 case 93:
-#line 621 "dcParser.yxx"
+#line 627 "dcParser.yxx"
 {
   yyval.u.subatomic = ST_int32;
 }
     break;
 case 94:
-#line 625 "dcParser.yxx"
+#line 631 "dcParser.yxx"
 {
   yyval.u.subatomic = ST_int64;
 }
     break;
 case 95:
-#line 629 "dcParser.yxx"
+#line 635 "dcParser.yxx"
 {
   yyval.u.subatomic = ST_uint8;
 }
     break;
 case 96:
-#line 633 "dcParser.yxx"
+#line 639 "dcParser.yxx"
 {
   yyval.u.subatomic = ST_uint16;
 }
     break;
 case 97:
-#line 637 "dcParser.yxx"
+#line 643 "dcParser.yxx"
 {
   yyval.u.subatomic = ST_uint32;
 }
     break;
 case 98:
-#line 641 "dcParser.yxx"
+#line 647 "dcParser.yxx"
 {
   yyval.u.subatomic = ST_uint64;
 }
     break;
 case 99:
-#line 645 "dcParser.yxx"
+#line 651 "dcParser.yxx"
 {
   yyval.u.subatomic = ST_float64;
 }
     break;
 case 100:
-#line 649 "dcParser.yxx"
+#line 655 "dcParser.yxx"
 {
   yyval.u.subatomic = ST_string;
 }
     break;
 case 101:
-#line 653 "dcParser.yxx"
+#line 659 "dcParser.yxx"
 {
   yyval.u.subatomic = ST_blob;
 }
     break;
 case 102:
-#line 657 "dcParser.yxx"
+#line 663 "dcParser.yxx"
 {
   yyval.u.subatomic = ST_blob32;
 }
     break;
 case 103:
-#line 661 "dcParser.yxx"
+#line 667 "dcParser.yxx"
 {
   yyval.u.subatomic = ST_int8array;
 }
     break;
 case 104:
-#line 665 "dcParser.yxx"
+#line 671 "dcParser.yxx"
 {
   yyval.u.subatomic = ST_int16array;
 }
     break;
 case 105:
-#line 669 "dcParser.yxx"
+#line 675 "dcParser.yxx"
 {
   yyval.u.subatomic = ST_int32array;
 }
     break;
 case 106:
-#line 673 "dcParser.yxx"
+#line 679 "dcParser.yxx"
 {
   yyval.u.subatomic = ST_uint8array;
 }
     break;
 case 107:
-#line 677 "dcParser.yxx"
+#line 683 "dcParser.yxx"
 {
   yyval.u.subatomic = ST_uint16array;
 }
     break;
 case 108:
-#line 681 "dcParser.yxx"
+#line 687 "dcParser.yxx"
 {
   yyval.u.subatomic = ST_uint32array;
 }
     break;
 case 109:
-#line 685 "dcParser.yxx"
+#line 691 "dcParser.yxx"
 {
   yyval.u.subatomic = ST_uint32uint8array;
 }
     break;
 case 111:
-#line 693 "dcParser.yxx"
+#line 699 "dcParser.yxx"
 {
   current_atomic->add_flag(DCAtomicField::F_required);
 }
     break;
 case 112:
-#line 697 "dcParser.yxx"
+#line 703 "dcParser.yxx"
 {
   current_atomic->add_flag(DCAtomicField::F_broadcast);
 }
     break;
 case 113:
-#line 701 "dcParser.yxx"
+#line 707 "dcParser.yxx"
 {
   current_atomic->add_flag(DCAtomicField::F_p2p);
 }
     break;
 case 114:
-#line 705 "dcParser.yxx"
+#line 711 "dcParser.yxx"
 {
   current_atomic->add_flag(DCAtomicField::F_ram);
 }
     break;
 case 115:
-#line 709 "dcParser.yxx"
+#line 715 "dcParser.yxx"
 {
   current_atomic->add_flag(DCAtomicField::F_db);
 }
     break;
 case 116:
-#line 713 "dcParser.yxx"
+#line 719 "dcParser.yxx"
 {
   current_atomic->add_flag(DCAtomicField::F_clsend);
 }
     break;
 case 117:
-#line 717 "dcParser.yxx"
+#line 723 "dcParser.yxx"
 {
   current_atomic->add_flag(DCAtomicField::F_clrecv);
 }
     break;
 case 118:
-#line 721 "dcParser.yxx"
+#line 727 "dcParser.yxx"
 {
   current_atomic->add_flag(DCAtomicField::F_ownsend);
 }
     break;
 case 119:
-#line 725 "dcParser.yxx"
+#line 731 "dcParser.yxx"
 {
   current_atomic->add_flag(DCAtomicField::F_airecv);
 }
     break;
 case 120:
-#line 732 "dcParser.yxx"
+#line 738 "dcParser.yxx"
 {
   current_molecular = new DCMolecularField(yyvsp[-1].str);
   if (!current_class->add_field(current_molecular)) {
@@ -1765,7 +1771,7 @@ case 120:
 }
     break;
 case 122:
-#line 743 "dcParser.yxx"
+#line 749 "dcParser.yxx"
 {
   if (yyvsp[0].u.atomic != (DCAtomicField *)NULL) {
     current_molecular->add_atomic(yyvsp[0].u.atomic);
@@ -1773,7 +1779,7 @@ case 122:
 }
     break;
 case 123:
-#line 749 "dcParser.yxx"
+#line 755 "dcParser.yxx"
 {
   if (yyvsp[0].u.atomic != (DCAtomicField *)NULL) {
     current_molecular->add_atomic(yyvsp[0].u.atomic);
@@ -2018,4 +2024,4 @@ yyreturn:
 #endif
   return yyresult;
 }
-#line 764 "dcParser.yxx"
+#line 770 "dcParser.yxx"

+ 9 - 3
direct/src/dcparser/dcParser.yxx

@@ -371,7 +371,9 @@ type_name:
         | type_token '(' double_range ')'
 {
   DCSimpleParameter *simple_param = new DCSimpleParameter($1);
-  simple_param->set_range(double_range);
+  if (!simple_param->set_range(double_range)) {
+    yyerror("Inappropriate range for type");
+  }
   $$ = simple_param;
 }
         | type_token '/' INTEGER
@@ -394,7 +396,9 @@ type_name:
   } else if (!simple_param->set_divisor($3)) {
     yyerror("A divisor is only valid on a numeric type.");
   }
-  simple_param->set_range(double_range);
+  if (!simple_param->set_range(double_range)) {
+    yyerror("Inappropriate range for type");
+  }
   $$ = simple_param;
 }
 	| type_token '(' double_range ')' '/' INTEGER
@@ -406,7 +410,9 @@ type_name:
   } else if (!simple_param->set_divisor($6)) {
     yyerror("A divisor is only valid on a numeric type.");
   }
-  simple_param->set_range(double_range);
+  if (!simple_param->set_range(double_range)) {
+    yyerror("Inappropriate range for type");
+  }
   $$ = simple_param;
 }
 	| IDENTIFIER

File diff suppressed because it is too large
+ 566 - 307
direct/src/dcparser/dcSimpleParameter.cxx


+ 29 - 15
direct/src/dcparser/dcSimpleParameter.h

@@ -48,29 +48,43 @@ PUBLISHED:
 
 public:
   bool set_divisor(int divisor);
-  void set_range(const DCDoubleRange &range);
+  bool set_range(const DCDoubleRange &range);
 
   virtual int calc_num_nested_fields(size_t length_bytes) const;
   virtual DCPackerInterface *get_nested_field(int n) const;
 
-  virtual bool pack_double(DCPackData &pack_data, double value) const;
-  virtual bool pack_int(DCPackData &pack_data, int value) const;
-  virtual bool pack_uint(DCPackData &pack_data, unsigned int value) const;
-  virtual bool pack_int64(DCPackData &pack_data, PN_int64 value) const;
-  virtual bool pack_uint64(DCPackData &pack_data, PN_uint64 value) const;
-  virtual bool pack_string(DCPackData &pack_data, const string &value) const;
-
-  virtual bool unpack_double(const char *data, size_t length, size_t &p, double &value) const;
-  virtual bool unpack_int(const char *data, size_t length, size_t &p, int &value) const;
-  virtual bool unpack_uint(const char *data, size_t length, size_t &p, unsigned int &value) const;
-  virtual bool unpack_int64(const char *data, size_t length, size_t &p, PN_int64 &value) const;
-  virtual bool unpack_uint64(const char *data, size_t length, size_t &p, PN_uint64 &value) const;
-  virtual bool unpack_string(const char *data, size_t length, size_t &p, string &value) const;
+  virtual void pack_double(DCPackData &pack_data, double value,
+                           bool &pack_error, bool &range_error) const;
+  virtual void pack_int(DCPackData &pack_data, int value,
+                        bool &pack_error, bool &range_error) const;
+  virtual void pack_uint(DCPackData &pack_data, unsigned int value,
+                         bool &pack_error, bool &range_error) const;
+  virtual void pack_int64(DCPackData &pack_data, PN_int64 value,
+                          bool &pack_error, bool &range_error) const;
+  virtual void pack_uint64(DCPackData &pack_data, PN_uint64 value,
+                           bool &pack_error, bool &range_error) const;
+  virtual void pack_string(DCPackData &pack_data, const string &value,
+                           bool &pack_error, bool &range_error) const;
+
+  virtual void unpack_double(const char *data, size_t length, size_t &p, 
+                             double &value, bool &pack_error, bool &range_error) const;
+  virtual void unpack_int(const char *data, size_t length, size_t &p, 
+                          int &value, bool &pack_error, bool &range_error) const;
+  virtual void unpack_uint(const char *data, size_t length, size_t &p, 
+                           unsigned int &value, bool &pack_error, bool &range_error) const;
+  virtual void unpack_int64(const char *data, size_t length, size_t &p, 
+                            PN_int64 &value, bool &pack_error, bool &range_error) const;
+  virtual void unpack_uint64(const char *data, size_t length, size_t &p, 
+                             PN_uint64 &value, bool &pack_error, bool &range_error) const;
+  virtual void unpack_string(const char *data, size_t length, size_t &p, 
+                             string &value, bool &pack_error, bool &range_error) const;
+  virtual bool unpack_validate(const char *data, size_t length, size_t &p, 
+                               bool &pack_error, bool &range_error) const;
   virtual bool unpack_skip(const char *data, size_t length, size_t &p) const;
 
   virtual void output_instance(ostream &out, const string &prename, 
                                const string &name, const string &postname) const;
-  virtual void generate_hash(HashGenerator &hash) const;
+  virtual void generate_hash(HashGenerator &hashgen) const;
 
 private:
   static DCSimpleParameter *create_nested_field(DCSubatomicType type, int divisor);

Some files were not shown because too many files changed in this diff