Author: rhs
Date: Mon Jul 23 07:34:45 2007
New Revision: 558741

URL: http://svn.apache.org/viewvc?view=rev&rev=558741
Log:
Applied a modified version of the range checking patch from QPID-498.

Modified:
    incubator/qpid/trunk/qpid/python/qpid/codec.py
    incubator/qpid/trunk/qpid/python/qpid/testlib.py

Modified: incubator/qpid/trunk/qpid/python/qpid/codec.py
URL: 
http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/python/qpid/codec.py?view=diff&rev=558741&r1=558740&r2=558741
==============================================================================
--- incubator/qpid/trunk/qpid/python/qpid/codec.py (original)
+++ incubator/qpid/trunk/qpid/python/qpid/codec.py Mon Jul 23 07:34:45 2007
@@ -22,8 +22,11 @@
 """
 Utility code to translate between python objects and AMQP encoded data
 fields.
+
+The unit test for this module is located in tests/codec.py
 """
 
+import re
 from cStringIO import StringIO
 from struct import *
 from reference import ReferenceId
@@ -33,7 +36,14 @@
 
 class Codec:
 
+  """
+  class that handles encoding/decoding of AMQP primitives
+  """
+
   def __init__(self, stream):
+    """
+    initializing the stream/fields used
+    """
     self.stream = stream
     self.nwrote = 0
     self.nread = 0
@@ -41,6 +51,9 @@
     self.outgoing_bits = []
 
   def read(self, n):
+    """
+    reads in 'n' bytes from the stream. Can raise EFO exception
+    """
     data = self.stream.read(n)
     if n > 0 and len(data) == 0:
       raise EOF()
@@ -48,15 +61,24 @@
     return data
 
   def write(self, s):
+    """
+    writes data 's' to the stream
+    """
     self.flushbits()
     self.stream.write(s)
     self.nwrote += len(s)
 
   def flush(self):
+    """
+    flushes the bits and data present in the stream
+    """
     self.flushbits()
     self.stream.flush()
 
   def flushbits(self):
+    """
+    flushes the bits(compressed into octets) onto the stream
+    """
     if len(self.outgoing_bits) > 0:
       bytes = []
       index = 0
@@ -69,9 +91,15 @@
         self.encode_octet(byte)
 
   def pack(self, fmt, *args):
+    """
+    packs the data 'args' as per the format 'fmt' and writes it to the stream
+    """
     self.write(pack(fmt, *args))
 
   def unpack(self, fmt):
+    """
+    reads data from the stream and unpacks it as per the format 'fmt'
+    """
     size = calcsize(fmt)
     data = self.read(size)
     values = unpack(fmt, data)
@@ -81,85 +109,166 @@
       return values
 
   def encode(self, type, value):
+    """
+    calls the appropriate encode function e.g. encode_octet, encode_short etc.
+    """
     getattr(self, "encode_" + type)(value)
 
   def decode(self, type):
+    """
+    calls the appropriate decode function e.g. decode_octet, decode_short etc.
+    """
     return getattr(self, "decode_" + type)()
 
-  # bit
   def encode_bit(self, o):
+    """
+    encodes a bit
+    """
     if o:
       self.outgoing_bits.append(True)
     else:
       self.outgoing_bits.append(False)
 
   def decode_bit(self):
+    """
+    decodes a bit
+    """
     if len(self.incoming_bits) == 0:
       bits = self.decode_octet()
       for i in range(8):
         self.incoming_bits.append(bits >> i & 1 != 0)
     return self.incoming_bits.pop(0)
 
-  # octet
   def encode_octet(self, o):
+    """
+    encodes octet (8 bits) data 'o' in network byte order
+    """
+
+    # octet's valid range is [0,255]
+    if (o < 0 or o > 255):
+        raise ValueError('Valid range of octet is [0,255]')
+
     self.pack("!B", o)
 
   def decode_octet(self):
+    """
+    decodes a octet (8 bits) encoded in network byte order
+    """
     return self.unpack("!B")
 
-  # short
   def encode_short(self, o):
+    """
+    encodes short (16 bits) data 'o' in network byte order
+    """
+
+    # short int's valid range is [0,65535]
+    if (o < 0 or o > 65535):
+        raise ValueError('Valid range of short int is [0,65535]')
+
     self.pack("!H", o)
 
   def decode_short(self):
+    """
+    decodes a short (16 bits) in network byte order
+    """
     return self.unpack("!H")
 
-  # long
   def encode_long(self, o):
+    """
+    encodes long (32 bits) data 'o' in network byte order
+    """
+
+    if (o < 0):
+        raise ValueError('unsinged long int cannot be less than 0')
+
     self.pack("!L", o)
 
   def decode_long(self):
+    """
+    decodes a long (32 bits) in network byte order
+    """
     return self.unpack("!L")
 
-  # longlong
   def encode_longlong(self, o):
+    """
+    encodes long long (64 bits) data 'o' in network byte order
+    """
     self.pack("!Q", o)
 
   def decode_longlong(self):
+    """
+    decodes a long long (64 bits) in network byte order
+    """
     return self.unpack("!Q")
 
   def enc_str(self, fmt, s):
+    """
+    encodes a string 's' in network byte order as per format 'fmt'
+    """
     size = len(s)
     self.pack(fmt, size)
     self.write(s)
 
   def dec_str(self, fmt):
+    """
+    decodes a string in network byte order as per format 'fmt'
+    """
     size = self.unpack(fmt)
     return self.read(size)
 
-  # shortstr
   def encode_shortstr(self, s):
+    """
+    encodes a short string 's' in network byte order
+    """
+
+    # short strings are limited to 255 octets
+    if len(s) > 255:
+        raise ValueError('Short strings are limited to 255 octets')
+
     self.enc_str("!B", s)
 
   def decode_shortstr(self):
+    """
+    decodes a short string in network byte order
+    """
     return self.dec_str("!B")
 
-  # longstr
   def encode_longstr(self, s):
+    """
+    encodes a long string 's' in network byte order
+    """
     if isinstance(s, dict):
       self.encode_table(s)
     else:
       self.enc_str("!L", s)
 
   def decode_longstr(self):
+    """
+    decodes a long string 's' in network byte order
+    """
     return self.dec_str("!L")
 
-  # table
+  KEY_CHECK = re.compile(r"[\$#A-Za-z][\$#A-Za-z0-9_]*")
+
   def encode_table(self, tbl):
+    """
+    encodes a table data structure in network byte order
+    """
     enc = StringIO()
     codec = Codec(enc)
     if tbl:
       for key, value in tbl.items():
+        # Field names MUST start with a letter, '$' or '#' and may
+        # continue with letters, '$' or '#', digits, or underlines, to
+        # a maximum length of 128 characters.
+
+        if len(key) > 128:
+          raise ValueError("field table key too long: '%s'" % key)
+
+        m = Codec.KEY_CHECK.match(key)
+        if m == None or m.end() != len(key):
+          raise ValueError("invalid field table key: '%s'" % key)
+
         codec.encode_shortstr(key)
         if isinstance(value, basestring):
           codec.write("S")
@@ -172,6 +281,9 @@
     self.write(s)
 
   def decode_table(self):
+    """
+    decodes a table data structure in network byte order
+    """
     size = self.decode_long()
     start = self.nread
     result = {}
@@ -188,27 +300,39 @@
     return result
 
   def encode_timestamp(self, t):
-    # XXX
+    """
+    encodes a timestamp data structure in network byte order
+    """
     self.encode_longlong(t)
 
   def decode_timestamp(self):
-    # XXX
+    """
+    decodes a timestamp data structure in network byte order
+    """
     return self.decode_longlong()
 
   def encode_content(self, s):
-    # content can be passed as a string in which case it is assumed to
-    # be inline data, or as an instance of ReferenceId indicating it is
-    # a reference id    
+    """
+    encodes a content data structure in network byte order
+
+    content can be passed as a string in which case it is assumed to
+    be inline data, or as an instance of ReferenceId indicating it is
+    a reference id
+    """
     if isinstance(s, ReferenceId):
       self.encode_octet(1)
       self.encode_longstr(s.id)
-    else:      
+    else:
       self.encode_octet(0)
       self.encode_longstr(s)
 
-  def decode_content(self):    
-    # return a string for inline data and a ReferenceId instance for
-    # references
+  def decode_content(self):
+    """
+    decodes a content data structure in network byte order
+
+    return a string for inline data and a ReferenceId instance for
+    references
+    """
     type = self.decode_octet()
     if type == 0:
       return self.decode_longstr()

Modified: incubator/qpid/trunk/qpid/python/qpid/testlib.py
URL: 
http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/python/qpid/testlib.py?view=diff&rev=558741&r1=558740&r2=558741
==============================================================================
--- incubator/qpid/trunk/qpid/python/qpid/testlib.py (original)
+++ incubator/qpid/trunk/qpid/python/qpid/testlib.py Mon Jul 23 07:34:45 2007
@@ -122,7 +122,7 @@
         print "Using specification from:", self.specfile
         self.spec = qpid.spec.load(self.specfile, *self.errata)
         if len(self.tests) == 0:
-#            self.tests=findmodules("tests")
+            self.tests=findmodules("tests")
             if self.use08spec():
                 self.tests+=findmodules("tests_0-8")
             else:


Reply via email to