python: Handle name/value is NULL but its length is positive

This happens when deflater local header table is smaller than
inflater header table size. We use the same notation
"**DEALLOCATED**" for such name/values with hdtest programs.
This commit is contained in:
Tatsuhiro Tsujikawa 2013-12-21 23:02:48 +09:00
parent c242150092
commit a2ceae23a3
2 changed files with 28 additions and 10 deletions

View File

@ -56,8 +56,11 @@ cdef extern from 'nghttp2_hd.h':
nghttp2_nv nv nghttp2_nv nv
uint8_t flags uint8_t flags
ctypedef struct nghttp2_hd_ringbuf:
size_t len
ctypedef struct nghttp2_hd_context: ctypedef struct nghttp2_hd_context:
size_t deflate_hd_tablelen nghttp2_hd_ringbuf hd_table
int nghttp2_hd_deflate_init2(nghttp2_hd_context *deflater, int nghttp2_hd_deflate_init2(nghttp2_hd_context *deflater,
nghttp2_hd_side side, nghttp2_hd_side side,

View File

@ -35,13 +35,15 @@ HD_ENTRY_OVERHEAD = cnghttp2.NGHTTP2_HD_ENTRY_OVERHEAD
class HDTableEntry: class HDTableEntry:
def __init__(self, name, value, ref): def __init__(self, name, namelen, value, valuelen, ref):
self.name = name self.name = name
self.namelen = namelen
self.value = value self.value = value
self.valuelen = valuelen
self.ref = ref self.ref = ref
def space(self): def space(self):
return len(self.name) + len(self.value) + HD_ENTRY_OVERHEAD return self.namelen + self.valuelen + HD_ENTRY_OVERHEAD
cdef class _HDContextBase: cdef class _HDContextBase:
@ -64,16 +66,28 @@ cdef class _HDContextBase:
def get_hd_table(self): def get_hd_table(self):
'''Returns copy of current dynamic header table.''' '''Returns copy of current dynamic header table.'''
cdef int length = self._ctx.deflate_hd_tablelen cdef int length = self._ctx.hd_table.len
cdef cnghttp2.nghttp2_hd_entry *entry cdef cnghttp2.nghttp2_hd_entry *entry
res = [] res = []
for i in range(length): for i in range(length):
entry = cnghttp2.nghttp2_hd_table_get(&self._ctx, i) entry = cnghttp2.nghttp2_hd_table_get(&self._ctx, i)
res.append(HDTableEntry(entry.nv.name[:entry.nv.namelen], k = _get_pybytes(entry.nv.name, entry.nv.namelen)
entry.nv.value[:entry.nv.valuelen], v = _get_pybytes(entry.nv.value, entry.nv.valuelen)
res.append(HDTableEntry(k, entry.nv.namelen,
v, entry.nv.valuelen,
(entry.flags & cnghttp2.NGHTTP2_HD_FLAG_REFSET) != 0)) (entry.flags & cnghttp2.NGHTTP2_HD_FLAG_REFSET) != 0))
return res return res
cdef _get_pybytes(uint8_t *b, uint16_t blen):
# While the |blen| is positive, the |b| could be NULL. This is
# because deflater may deallocate the byte strings its local table
# space.
if b == NULL and blen > 0:
val = None
else:
val = b[:blen]
return val
cdef class HDDeflater(_HDContextBase): cdef class HDDeflater(_HDContextBase):
'''Performs header compression. The header compression algorithm has '''Performs header compression. The header compression algorithm has
to know the header set to be compressed is request headers or to know the header set to be compressed is request headers or
@ -215,7 +229,8 @@ def print_hd_table(hdtable):
idx = 0 idx = 0
for entry in hdtable: for entry in hdtable:
idx += 1 idx += 1
print('[{}] (s={}) (r={}) {}: {}'.format(idx, entry.space(), print('[{}] (s={}) (r={}) {}: {}'\
'y' if entry.ref else 'n', .format(idx, entry.space(),
entry.name.decode('utf-8'), 'y' if entry.ref else 'n',
entry.value.decode('utf-8'))) '**DEALLOCATED**' if entry.name is None else entry.name.decode('utf-8'),
'**DEALLOCATED**' if entry.value is None else entry.value.decode('utf-8')))