2011-12-21 09:55:05 +00:00
/*
Serval Distributed Numbering Architecture ( DNA )
Copyright ( C ) 2010 Paul Gardner - Stephen
This program is free software ; you can redistribute it and / or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation ; either version 2
of the License , or ( at your option ) any later version .
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
You should have received a copy of the GNU General Public License
along with this program ; if not , write to the Free Software
Foundation , Inc . , 51 Franklin Street , Fifth Floor , Boston , MA 02110 - 1301 , USA .
*/
2013-11-25 06:13:32 +00:00
# include <assert.h>
2012-02-23 02:15:42 +00:00
# include "serval.h"
2012-12-11 05:29:46 +00:00
# include "conf.h"
# include "mem.h"
2012-08-22 00:51:38 +00:00
# include "overlay_buffer.h"
2011-08-08 06:41:05 +00:00
2012-08-22 00:51:38 +00:00
/*
When writing to a buffer , sizeLimit may place an upper bound on the amount of space to use
When reading from a buffer , sizeLimit should first be set to the length of any existing data .
In either case , functions that don ' t take an offset use and advance the position .
*/
2013-11-22 14:29:11 +00:00
struct overlay_buffer * _ob_new ( struct __sourceloc __whence )
2011-08-08 06:41:05 +00:00
{
2013-11-25 06:13:32 +00:00
struct overlay_buffer * ret = emalloc_zero ( sizeof ( struct overlay_buffer ) ) ;
2013-11-22 14:29:11 +00:00
if ( config . debug . overlaybuffer )
DEBUGF ( " ob_new() return %p " , ret ) ;
2013-11-25 06:13:32 +00:00
if ( ret = = NULL )
return NULL ;
2011-08-08 06:41:05 +00:00
ob_unlimitsize ( ret ) ;
return ret ;
}
2012-07-18 05:00:16 +00:00
// index an existing static buffer.
// and allow other callers to use the ob_ convenience methods for reading and writing up to size bytes.
2013-12-10 06:33:30 +00:00
struct overlay_buffer * _ob_static ( struct __sourceloc __whence , unsigned char * bytes , size_t size )
2013-11-25 06:13:32 +00:00
{
struct overlay_buffer * ret = emalloc_zero ( sizeof ( struct overlay_buffer ) ) ;
2013-11-22 14:29:11 +00:00
if ( config . debug . overlaybuffer )
2013-12-10 06:33:30 +00:00
DEBUGF ( " ob_static(bytes=%p, size=%zu) return %p " , bytes , size , ret ) ;
2013-11-25 06:13:32 +00:00
if ( ret = = NULL )
return NULL ;
2012-07-18 05:00:16 +00:00
ret - > bytes = bytes ;
2012-08-22 00:51:38 +00:00
ret - > allocSize = size ;
2012-11-27 04:02:10 +00:00
ret - > allocated = NULL ;
2012-08-22 00:51:38 +00:00
ob_unlimitsize ( ret ) ;
2012-07-18 05:00:16 +00:00
return ret ;
}
2012-08-22 00:51:38 +00:00
// create a new overlay buffer from an existing piece of another buffer.
// Both buffers will point to the same memory region.
// It is up to the caller to ensure this buffer is not used after the parent buffer is freed.
2013-12-10 06:33:30 +00:00
struct overlay_buffer * _ob_slice ( struct __sourceloc __whence , struct overlay_buffer * b , size_t offset , size_t length )
2013-11-25 06:13:32 +00:00
{
2013-12-10 06:33:30 +00:00
if ( offset + length > b - > allocSize ) {
2012-10-15 05:06:36 +00:00
WHY ( " Buffer isn't long enough to slice " ) ;
2013-11-25 06:13:32 +00:00
return NULL ;
2012-10-15 05:06:36 +00:00
}
2013-11-25 06:13:32 +00:00
struct overlay_buffer * ret = emalloc_zero ( sizeof ( struct overlay_buffer ) ) ;
2013-11-22 14:29:11 +00:00
if ( config . debug . overlaybuffer )
2013-12-10 06:33:30 +00:00
DEBUGF ( " ob_slice(b=%p, offset=%zu, length=%zu) return %p " , b , offset , length , ret ) ;
2013-11-25 06:13:32 +00:00
if ( ret = = NULL )
2012-08-27 00:34:59 +00:00
return NULL ;
2013-12-10 06:33:30 +00:00
ret - > bytes = b - > bytes + offset ;
2012-08-22 00:51:38 +00:00
ret - > allocSize = length ;
2012-11-27 04:02:10 +00:00
ret - > allocated = NULL ;
2012-08-22 00:51:38 +00:00
ob_unlimitsize ( ret ) ;
return ret ;
}
2013-11-22 14:29:11 +00:00
struct overlay_buffer * _ob_dup ( struct __sourceloc __whence , struct overlay_buffer * b )
2013-11-25 06:13:32 +00:00
{
struct overlay_buffer * ret = emalloc_zero ( sizeof ( struct overlay_buffer ) ) ;
2013-11-22 14:29:11 +00:00
if ( config . debug . overlaybuffer )
DEBUGF ( " ob_dup(b=%p) return %p " , b , ret ) ;
2013-11-25 06:13:32 +00:00
if ( ret = = NULL )
return NULL ;
2012-08-22 00:51:38 +00:00
ret - > sizeLimit = b - > sizeLimit ;
ret - > position = b - > position ;
ret - > checkpointLength = b - > checkpointLength ;
2012-08-27 00:34:59 +00:00
if ( b - > bytes & & b - > allocSize ) {
// duplicate any bytes that might be relevant
2013-12-10 06:33:30 +00:00
size_t byteCount = b - > position ;
if ( b - > sizeLimit ! = SIZE_MAX ) {
assert ( b - > position < = b - > sizeLimit ) ;
byteCount = b - > sizeLimit ;
}
2012-08-22 00:51:38 +00:00
if ( byteCount > b - > allocSize )
byteCount = b - > allocSize ;
2013-11-25 06:13:32 +00:00
if ( byteCount )
ob_append_bytes ( ret , b - > bytes , byteCount ) ;
2012-08-22 00:51:38 +00:00
}
return ret ;
}
2013-11-22 14:29:11 +00:00
void _ob_free ( struct __sourceloc __whence , struct overlay_buffer * b )
2011-08-08 06:41:05 +00:00
{
2013-11-25 06:13:32 +00:00
assert ( b ! = NULL ) ;
2013-11-22 14:29:11 +00:00
if ( config . debug . overlaybuffer )
DEBUGF ( " ob_free(b=%p) " , b ) ;
2013-11-25 06:13:32 +00:00
if ( b - > allocated )
free ( b - > allocated ) ;
2011-08-08 06:41:05 +00:00
free ( b ) ;
}
2013-11-22 14:29:11 +00:00
int _ob_checkpoint ( struct __sourceloc __whence , struct overlay_buffer * b )
2011-08-08 06:41:05 +00:00
{
2013-11-25 06:13:32 +00:00
assert ( b ! = NULL ) ;
b - > checkpointLength = b - > position ;
2013-11-22 14:29:11 +00:00
if ( config . debug . overlaybuffer )
2013-12-10 06:33:30 +00:00
DEBUGF ( " ob_checkpoint(b=%p) checkpointLength=%zu " , b , b - > checkpointLength ) ;
2011-08-08 06:41:05 +00:00
return 0 ;
}
2013-11-22 14:29:11 +00:00
int _ob_rewind ( struct __sourceloc __whence , struct overlay_buffer * b )
2011-08-08 06:41:05 +00:00
{
2013-11-25 06:13:32 +00:00
assert ( b ! = NULL ) ;
b - > position = b - > checkpointLength ;
2013-11-22 14:29:11 +00:00
if ( config . debug . overlaybuffer )
2013-12-10 06:33:30 +00:00
DEBUGF ( " ob_rewind(b=%p) position=%zu " , b , b - > position ) ;
2011-08-08 06:41:05 +00:00
return 0 ;
}
2013-12-10 06:33:30 +00:00
void _ob_limitsize ( struct __sourceloc __whence , struct overlay_buffer * b , size_t bytes )
2011-08-08 06:41:05 +00:00
{
2013-11-25 06:13:32 +00:00
assert ( b ! = NULL ) ;
2013-12-10 06:33:30 +00:00
assert ( bytes ! = SIZE_MAX ) ;
2013-11-25 06:13:32 +00:00
assert ( b - > position < = bytes ) ;
assert ( b - > checkpointLength < = bytes ) ;
if ( b - > bytes & & b - > allocated = = NULL )
assert ( bytes < = b - > allocSize ) ;
2013-11-22 14:29:11 +00:00
b - > sizeLimit = bytes ;
if ( config . debug . overlaybuffer )
2013-12-10 06:33:30 +00:00
DEBUGF ( " ob_limitsize(b=%p, bytes=%zu) sizeLimit=%zu " , b , bytes , b - > sizeLimit ) ;
2011-08-08 06:41:05 +00:00
}
2013-11-22 14:29:11 +00:00
void _ob_unlimitsize ( struct __sourceloc __whence , struct overlay_buffer * b )
2011-08-08 06:41:05 +00:00
{
2013-11-25 06:13:32 +00:00
assert ( b ! = NULL ) ;
2013-12-10 06:33:30 +00:00
b - > sizeLimit = SIZE_MAX ;
2013-11-22 14:29:11 +00:00
if ( config . debug . overlaybuffer )
2013-12-10 06:33:30 +00:00
DEBUGF ( " ob_unlimitsize(b=%p) sizeLimit=%zu " , b , b - > sizeLimit ) ;
2011-08-08 06:41:05 +00:00
}
2013-11-22 14:29:11 +00:00
void _ob_flip ( struct __sourceloc __whence , struct overlay_buffer * b )
2013-09-11 07:45:43 +00:00
{
2013-11-22 14:29:11 +00:00
if ( config . debug . overlaybuffer )
DEBUGF ( " ob_flip(b=%p) checkpointLength=0 position=0 " , b ) ;
2013-11-25 06:13:32 +00:00
b - > checkpointLength = 0 ;
ob_limitsize ( b , b - > position ) ;
b - > position = 0 ;
2013-09-11 07:45:43 +00:00
}
2013-11-25 06:13:32 +00:00
/* Return 1 if space is available, 0 if not.
*/
2013-11-22 14:29:11 +00:00
ssize_t _ob_makespace ( struct __sourceloc __whence , struct overlay_buffer * b , size_t bytes )
2011-08-08 06:41:05 +00:00
{
2013-11-25 06:13:32 +00:00
assert ( b ! = NULL ) ;
2013-11-22 14:29:11 +00:00
if ( config . debug . overlaybuffer )
2013-12-10 06:33:30 +00:00
DEBUGF ( " ob_makespace(b=%p, bytes=%zd) b->bytes=%p b->position=%zu b->allocSize=%zu " ,
2013-11-22 14:29:11 +00:00
b , bytes , b - > bytes , b - > position , b - > allocSize ) ;
2013-12-10 06:33:30 +00:00
assert ( b - > position < = b - > sizeLimit ) ;
assert ( b - > position < = b - > allocSize ) ;
2013-11-25 06:13:32 +00:00
if ( b - > position )
assert ( b - > bytes ! = NULL ) ;
2013-12-10 06:33:30 +00:00
if ( b - > position + bytes > b - > sizeLimit ) {
2013-11-22 14:29:11 +00:00
if ( config . debug . packetformats )
2013-12-10 06:33:30 +00:00
DEBUGF ( " ob_makespace(): asked for space to %zu, beyond size limit of %zu " , b - > position + bytes , b - > sizeLimit ) ;
2013-11-25 06:13:32 +00:00
return 0 ;
2013-11-22 14:29:11 +00:00
}
2013-02-22 05:57:37 +00:00
if ( b - > position + bytes < = b - > allocSize )
2013-11-25 06:13:32 +00:00
return 1 ;
// Don't realloc a static buffer.
2013-11-22 14:29:11 +00:00
if ( b - > bytes & & b - > allocated = = NULL ) {
if ( config . debug . packetformats )
2013-12-10 06:33:30 +00:00
DEBUGF ( " ob_makespace(): asked for space to %zu, beyond static buffer size of %zu " , b - > position + bytes , b - > allocSize ) ;
2012-08-22 00:51:38 +00:00
return 0 ;
2013-11-22 14:29:11 +00:00
}
2013-12-10 06:33:30 +00:00
size_t newSize = b - > position + bytes ;
2012-08-22 00:51:38 +00:00
if ( newSize < 64 ) newSize = 64 ;
if ( newSize & 63 ) newSize + = 64 - ( newSize & 63 ) ;
2013-11-25 06:13:32 +00:00
if ( newSize > 1024 & & ( newSize & 1023 ) )
newSize + = 1024 - ( newSize & 1023 ) ;
if ( newSize > 65536 & & ( newSize & 65535 ) )
newSize + = 65536 - ( newSize & 65535 ) ;
if ( config . debug . overlaybuffer )
2013-12-10 06:33:30 +00:00
DEBUGF ( " realloc(b->bytes=%p, newSize=%zu) " , b - > bytes , newSize ) ;
2012-08-22 00:51:38 +00:00
/* XXX OSX realloc() seems to be able to corrupt things if the heap is not happy when calling realloc(), making debugging memory corruption much harder.
2013-11-25 06:13:32 +00:00
So will do a three - stage malloc , bcopy , free to see if we can tease bugs out that way . */
2012-08-22 00:51:38 +00:00
/*
unsigned char * r = realloc ( b - > bytes , newSize ) ;
if ( ! r ) return WHY ( " realloc() failed " ) ;
b - > bytes = r ;
*/
2012-03-22 20:36:57 +00:00
# ifdef MALLOC_PARANOIA
2012-03-22 06:40:27 +00:00
# warning adding lots of padding to try to catch overruns
2012-08-22 00:51:38 +00:00
if ( b - > bytes ) {
int i ;
int corrupt = 0 ;
for ( i = 0 ; i < 4096 ; i + + ) if ( b - > bytes [ b - > allocSize + i ] ! = 0xbd ) corrupt + + ;
if ( corrupt ) {
WHYF ( " !!!!!! %d corrupted bytes in overrun catch tray " , corrupt ) ;
dump ( " overrun catch tray " , & b - > bytes [ b - > allocSize ] , 4096 ) ;
2013-08-27 05:44:17 +00:00
sleep_ms ( 36000000 ) ;
2012-08-22 00:51:38 +00:00
}
}
2013-11-25 06:13:32 +00:00
unsigned char * new = emalloc ( newSize + 4096 ) ;
2012-08-22 00:51:38 +00:00
{
int i ;
for ( i = 0 ; i < 4096 ; i + + ) new [ newSize + i ] = 0xbd ;
}
2012-03-22 20:36:57 +00:00
# else
2013-11-25 06:13:32 +00:00
unsigned char * new = emalloc ( newSize ) ;
2012-03-22 20:36:57 +00:00
# endif
2013-11-25 06:13:32 +00:00
if ( ! new )
return 0 ;
2012-08-22 00:51:38 +00:00
bcopy ( b - > bytes , new , b - > position ) ;
2013-11-25 06:13:32 +00:00
if ( b - > allocated ) {
assert ( b - > allocated = = b - > bytes ) ;
free ( b - > allocated ) ;
}
2012-08-22 00:51:38 +00:00
b - > bytes = new ;
2012-11-27 04:02:10 +00:00
b - > allocated = new ;
2012-08-22 00:51:38 +00:00
b - > allocSize = newSize ;
2013-11-25 06:13:32 +00:00
return 1 ;
2011-08-08 06:41:05 +00:00
}
2012-07-18 05:00:16 +00:00
/*
Functions that append data and increase the size of the buffer if possible / required
*/
2013-11-22 14:29:11 +00:00
void _ob_append_byte ( struct __sourceloc __whence , struct overlay_buffer * b , unsigned char byte )
2011-09-03 21:06:39 +00:00
{
2013-11-25 06:13:32 +00:00
const int bytes = 1 ;
2013-11-22 14:29:11 +00:00
if ( ob_makespace ( b , bytes ) ) {
2013-11-25 06:13:32 +00:00
b - > bytes [ b - > position ] = byte ;
2013-11-22 14:29:11 +00:00
if ( config . debug . overlaybuffer )
2013-12-16 04:49:15 +00:00
DEBUGF ( " ob_append_byte(b=%p, byte=0x%02x) %p[%zd]=%02x position=%zu " , b , byte , b - > bytes , b - > position , byte , b - > position + bytes ) ;
2013-11-22 14:29:11 +00:00
} else {
if ( config . debug . overlaybuffer )
2013-12-10 06:33:30 +00:00
DEBUGF ( " ob_append_byte(b=%p, byte=0x%02x) OVERRUN position=%zu " , b , byte , b - > position + bytes ) ;
2013-11-22 14:29:11 +00:00
}
2013-11-25 06:13:32 +00:00
b - > position + = bytes ;
2011-09-03 21:06:39 +00:00
}
2013-12-10 06:33:30 +00:00
unsigned char * _ob_append_space ( struct __sourceloc __whence , struct overlay_buffer * b , size_t count )
2012-04-13 16:44:41 +00:00
{
2013-11-25 06:13:32 +00:00
assert ( count > 0 ) ;
unsigned char * r = ob_makespace ( b , count ) ? & b - > bytes [ b - > position ] : NULL ;
b - > position + = count ;
2013-11-22 14:29:11 +00:00
if ( config . debug . overlaybuffer )
2013-12-10 06:33:30 +00:00
DEBUGF ( " ob_append_space(b=%p, count=%zu) position=%zu return %p " , b , count , b - > position , r ) ;
2012-04-13 16:44:41 +00:00
return r ;
}
2013-12-10 06:33:30 +00:00
void _ob_append_bytes ( struct __sourceloc __whence , struct overlay_buffer * b , const unsigned char * bytes , size_t count )
2011-08-08 06:41:05 +00:00
{
2013-11-25 06:13:32 +00:00
assert ( count > 0 ) ;
unsigned char * r = ob_makespace ( b , count ) ? & b - > bytes [ b - > position ] : NULL ;
2013-11-22 14:29:11 +00:00
if ( r ) {
2013-11-25 06:13:32 +00:00
bcopy ( bytes , r , count ) ;
2013-11-22 14:29:11 +00:00
if ( config . debug . overlaybuffer )
2013-12-10 06:33:30 +00:00
DEBUGF ( " ob_append_bytes(b=%p, bytes=%p, count=%zu) position=%zu return %p " , b , bytes , count , b - > position + count , r ) ;
2013-11-22 14:29:11 +00:00
} else {
if ( config . debug . overlaybuffer )
2013-12-10 06:33:30 +00:00
DEBUGF ( " ob_append_bytes(b=%p, bytes=%p, count=%zu) OVERRUN position=%zu return NULL " , b , bytes , count , b - > position + count ) ;
2013-11-22 14:29:11 +00:00
}
if ( config . debug . overlaybuffer )
dump ( " ob_append_bytes " , bytes , count ) ;
2013-11-25 06:13:32 +00:00
b - > position + = count ;
2011-08-08 06:41:05 +00:00
}
2013-11-22 14:29:11 +00:00
void _ob_append_buffer ( struct __sourceloc __whence , struct overlay_buffer * b , struct overlay_buffer * s )
2013-11-25 06:13:32 +00:00
{
ob_append_bytes ( b , s - > bytes , s - > position ) ;
2013-02-14 03:48:56 +00:00
}
2013-11-22 14:29:11 +00:00
void _ob_append_ui16 ( struct __sourceloc __whence , struct overlay_buffer * b , uint16_t v )
2011-08-08 06:41:05 +00:00
{
2013-11-25 06:13:32 +00:00
const int bytes = 2 ;
if ( ob_makespace ( b , bytes ) ) {
b - > bytes [ b - > position ] = ( v > > 8 ) & 0xFF ;
b - > bytes [ b - > position + 1 ] = v & 0xFF ;
2013-11-22 14:29:11 +00:00
if ( config . debug . overlaybuffer )
2013-12-16 04:49:15 +00:00
DEBUGF ( " ob_append_ui16(b=%p, v=%u) %p[%zd]=%s position=%zu " , b , v , b - > bytes , b - > position , alloca_tohex ( & b - > bytes [ b - > position ] , bytes ) , b - > position + bytes ) ;
2013-11-22 14:29:11 +00:00
} else {
if ( config . debug . overlaybuffer )
2013-12-10 06:33:30 +00:00
DEBUGF ( " ob_append_ui16(b=%p, v=%u) OVERRUN position=%zu " , b , v , b - > position + bytes ) ;
2013-11-25 06:13:32 +00:00
}
b - > position + = bytes ;
2011-08-08 06:41:05 +00:00
}
2013-11-22 14:29:11 +00:00
void _ob_append_ui32 ( struct __sourceloc __whence , struct overlay_buffer * b , uint32_t v )
2011-08-08 06:41:05 +00:00
{
2013-11-25 06:13:32 +00:00
const int bytes = 4 ;
if ( ob_makespace ( b , bytes ) ) {
b - > bytes [ b - > position ] = ( v > > 24 ) & 0xFF ;
b - > bytes [ b - > position + 1 ] = ( v > > 16 ) & 0xFF ;
b - > bytes [ b - > position + 2 ] = ( v > > 8 ) & 0xFF ;
b - > bytes [ b - > position + 3 ] = v & 0xFF ;
2013-11-22 14:29:11 +00:00
if ( config . debug . overlaybuffer )
2013-12-16 04:49:15 +00:00
DEBUGF ( " ob_append_ui32(b=%p, v=% " PRIu32 " ) %p[%zd]=%s position=%zu " ,
2013-11-22 14:29:11 +00:00
b , v , b - > bytes , b - > position , alloca_tohex ( & b - > bytes [ b - > position ] , bytes ) , b - > position + bytes ) ;
} else {
if ( config . debug . overlaybuffer )
2013-12-10 06:33:30 +00:00
DEBUGF ( " ob_append_ui32(b=%p, v=% " PRIu32 " ) OVERRUN position=%zu " , b , v , b - > position + bytes ) ;
2013-11-25 06:13:32 +00:00
}
b - > position + = bytes ;
2011-08-08 06:41:05 +00:00
}
2011-08-17 01:22:17 +00:00
2013-11-22 14:29:11 +00:00
void _ob_append_ui64 ( struct __sourceloc __whence , struct overlay_buffer * b , uint64_t v )
2013-06-18 03:57:26 +00:00
{
2013-11-25 06:13:32 +00:00
const int bytes = 8 ;
if ( ob_makespace ( b , bytes ) ) {
b - > bytes [ b - > position ] = ( v > > 56 ) & 0xFF ;
b - > bytes [ b - > position + 1 ] = ( v > > 48 ) & 0xFF ;
b - > bytes [ b - > position + 2 ] = ( v > > 40 ) & 0xFF ;
b - > bytes [ b - > position + 3 ] = ( v > > 32 ) & 0xFF ;
b - > bytes [ b - > position + 4 ] = ( v > > 24 ) & 0xFF ;
b - > bytes [ b - > position + 5 ] = ( v > > 16 ) & 0xFF ;
b - > bytes [ b - > position + 6 ] = ( v > > 8 ) & 0xFF ;
b - > bytes [ b - > position + 7 ] = v & 0xFF ;
2013-11-22 14:29:11 +00:00
if ( config . debug . overlaybuffer )
2013-12-16 04:49:15 +00:00
DEBUGF ( " ob_append_ui64(b=%p, v=% " PRIu64 " ) %p[%zd]=%s position=%zu " ,
2013-11-22 14:29:11 +00:00
b , v , b - > bytes , b - > position , alloca_tohex ( & b - > bytes [ b - > position ] , bytes ) , b - > position + bytes ) ;
} else {
if ( config . debug . overlaybuffer )
2013-12-10 06:33:30 +00:00
DEBUGF ( " ob_append_ui64(b=%p, v=% " PRIu64 " ) OVERRUN position=%zu " , b , v , b - > position + bytes ) ;
2013-11-25 06:13:32 +00:00
}
b - > position + = bytes ;
2013-06-18 03:57:26 +00:00
}
2013-07-23 04:51:46 +00:00
int measure_packed_uint ( uint64_t v ) {
2013-07-31 01:03:46 +00:00
int ret = 0 ;
do {
2013-07-23 04:51:46 +00:00
v > > = 7 ;
ret + + ;
2013-07-31 01:03:46 +00:00
} while ( v ) ;
2013-07-23 04:51:46 +00:00
return ret ;
}
int pack_uint ( unsigned char * buffer , uint64_t v ) {
int ret = 0 ;
do {
* buffer + + = ( v & 0x7f ) | ( v > 0x7f ? 0x80 : 0 ) ;
v > > = 7 ;
ret + + ;
} while ( v ) ;
return ret ;
}
int unpack_uint ( unsigned char * buffer , int buff_size , uint64_t * v ) {
int i = 0 ;
* v = 0 ;
while ( 1 ) {
if ( i > = buff_size )
return - 1 ;
char byte = buffer [ i ] ;
* v | = ( byte & 0x7f ) < < ( i * 7 ) ;
i + + ;
if ( ! ( byte & 0x80 ) )
break ;
}
return i ;
}
2013-11-22 14:29:11 +00:00
void _ob_append_packed_ui32 ( struct __sourceloc __whence , struct overlay_buffer * b , uint32_t v )
2012-11-28 03:01:33 +00:00
{
2013-11-25 06:13:32 +00:00
do {
ob_append_byte ( b , ( v & 0x7f ) | ( v > 0x7f ? 0x80 : 0 ) ) ;
v = v > > 7 ;
} while ( v ! = 0 ) ;
2012-11-28 03:01:33 +00:00
}
2013-11-22 14:29:11 +00:00
void _ob_append_packed_ui64 ( struct __sourceloc __whence , struct overlay_buffer * b , uint64_t v )
2013-06-18 03:57:26 +00:00
{
2013-11-25 06:13:32 +00:00
do {
ob_append_byte ( b , ( v & 0x7f ) | ( v > 0x7f ? 0x80 : 0 ) ) ;
v = v > > 7 ;
} while ( v ! = 0 ) ;
2013-06-18 03:57:26 +00:00
}
2013-11-22 14:29:11 +00:00
void _ob_append_rfs ( struct __sourceloc __whence , struct overlay_buffer * b , int l )
2011-08-17 01:22:17 +00:00
{
2013-11-25 06:13:32 +00:00
assert ( l > = 0 ) ;
assert ( l < = 0xffff ) ;
b - > var_length_offset = b - > position ;
ob_append_ui16 ( b , l ) ;
2012-07-18 05:00:16 +00:00
}
/*
Functions that read / write data within the existing length limit
*/
2012-08-22 00:51:38 +00:00
// make sure a range of bytes is valid for reading
2013-12-10 06:33:30 +00:00
static int test_offset ( struct overlay_buffer * b , size_t length )
2013-11-25 06:13:32 +00:00
{
2013-12-10 06:33:30 +00:00
if ( b - > position + length > b - > sizeLimit )
return - 1 ;
if ( b - > position + length > b - > allocSize )
return - 1 ;
2012-07-18 05:00:16 +00:00
return 0 ;
}
2011-08-17 01:22:17 +00:00
2013-11-28 07:14:37 +00:00
// next byte without advancing
int ob_peek ( struct overlay_buffer * b )
2012-07-18 05:00:16 +00:00
{
2013-12-10 06:33:30 +00:00
if ( test_offset ( b , 1 ) )
2012-08-22 00:51:38 +00:00
return - 1 ;
2013-11-28 07:14:37 +00:00
return b - > bytes [ b - > position ] ;
}
void ob_skip ( struct overlay_buffer * b , unsigned n )
{
b - > position + = n ;
2012-08-22 00:51:38 +00:00
}
2013-12-10 06:33:30 +00:00
int ob_get_bytes ( struct overlay_buffer * b , unsigned char * buff , size_t len )
{
if ( test_offset ( b , len ) )
2012-08-22 00:51:38 +00:00
return - 1 ;
bcopy ( b - > bytes + b - > position , buff , len ) ;
b - > position + = len ;
2012-07-18 05:00:16 +00:00
return 0 ;
}
2013-12-10 06:33:30 +00:00
unsigned char * ob_get_bytes_ptr ( struct overlay_buffer * b , size_t len )
{
if ( test_offset ( b , len ) )
2012-08-22 00:51:38 +00:00
return NULL ;
unsigned char * ret = b - > bytes + b - > position ;
b - > position + = len ;
return ret ;
}
uint32_t ob_get_ui32 ( struct overlay_buffer * b )
2012-07-18 05:00:16 +00:00
{
2013-12-10 06:33:30 +00:00
if ( test_offset ( b , 4 ) )
2012-08-22 00:51:38 +00:00
return 0xFFFFFFFF ; // ... unsigned
uint32_t ret = b - > bytes [ b - > position ] < < 24
| b - > bytes [ b - > position + 1 ] < < 16
| b - > bytes [ b - > position + 2 ] < < 8
| b - > bytes [ b - > position + 3 ] ;
b - > position + = 4 ;
return ret ;
2012-07-18 05:00:16 +00:00
}
2013-06-18 03:57:26 +00:00
uint64_t ob_get_ui64 ( struct overlay_buffer * b )
{
2013-12-10 06:33:30 +00:00
if ( test_offset ( b , 8 ) )
2013-06-18 03:57:26 +00:00
return 0xFFFFFFFF ; // ... unsigned
uint64_t ret = ( uint64_t ) b - > bytes [ b - > position ] < < 56
| ( uint64_t ) b - > bytes [ b - > position + 1 ] < < 48
| ( uint64_t ) b - > bytes [ b - > position + 2 ] < < 40
| ( uint64_t ) b - > bytes [ b - > position + 3 ] < < 36
| b - > bytes [ b - > position + 4 ] < < 24
| b - > bytes [ b - > position + 5 ] < < 16
| b - > bytes [ b - > position + 6 ] < < 8
| b - > bytes [ b - > position + 7 ] ;
b - > position + = 8 ;
return ret ;
}
2012-08-22 00:51:38 +00:00
uint16_t ob_get_ui16 ( struct overlay_buffer * b )
2012-07-18 05:00:16 +00:00
{
2013-12-10 06:33:30 +00:00
if ( test_offset ( b , 2 ) )
2012-08-22 00:51:38 +00:00
return 0xFFFF ; // ... unsigned
uint16_t ret = b - > bytes [ b - > position ] < < 8
| b - > bytes [ b - > position + 1 ] ;
b - > position + = 2 ;
return ret ;
}
2012-07-18 05:00:16 +00:00
2012-11-28 03:01:33 +00:00
uint32_t ob_get_packed_ui32 ( struct overlay_buffer * b )
{
uint32_t ret = 0 ;
int shift = 0 ;
int byte ;
do {
byte = ob_get ( b ) ;
if ( byte < 0 )
return WHY ( " Failed to unpack integer " ) ;
ret | = ( byte & 0x7f ) < < shift ;
shift + = 7 ;
} while ( byte & 0x80 ) ;
return ret ;
}
2013-06-18 03:57:26 +00:00
uint64_t ob_get_packed_ui64 ( struct overlay_buffer * b )
{
uint64_t ret = 0 ;
int shift = 0 ;
int byte ;
do {
byte = ob_get ( b ) ;
if ( byte < 0 )
return WHY ( " Failed to unpack integer " ) ;
ret | = ( byte & 0x7f ) < < shift ;
shift + = 7 ;
} while ( byte & 0x80 ) ;
return ret ;
}
2013-11-22 14:29:11 +00:00
int ob_get ( struct overlay_buffer * b )
{
2013-12-10 06:33:30 +00:00
if ( test_offset ( b , 1 ) )
2012-08-22 00:51:38 +00:00
return - 1 ;
return b - > bytes [ b - > position + + ] ;
2011-08-17 01:22:17 +00:00
}
2013-12-10 06:33:30 +00:00
void _ob_set_ui16 ( struct __sourceloc __whence , struct overlay_buffer * b , size_t offset , uint16_t v )
2011-08-17 01:22:17 +00:00
{
2013-11-22 14:29:11 +00:00
const int bytes = 2 ;
2013-11-25 06:13:32 +00:00
assert ( b ! = NULL ) ;
2013-12-10 06:33:30 +00:00
assert ( offset + bytes < = b - > sizeLimit ) ;
2013-11-22 14:29:11 +00:00
assert ( offset + bytes < = b - > allocSize ) ;
2012-11-23 03:04:01 +00:00
b - > bytes [ offset ] = ( v > > 8 ) & 0xFF ;
b - > bytes [ offset + 1 ] = v & 0xFF ;
2013-11-22 14:29:11 +00:00
if ( config . debug . overlaybuffer )
2013-12-16 04:49:15 +00:00
DEBUGF ( " ob_set_ui16(b=%p, offset=%zd, v=%u) %p[%zd]=%s " , b , offset , v , b - > bytes , offset , alloca_tohex ( & b - > bytes [ offset ] , bytes ) ) ;
2011-08-17 01:22:17 +00:00
}
2013-12-10 06:33:30 +00:00
void _ob_set ( struct __sourceloc __whence , struct overlay_buffer * b , size_t offset , unsigned char byte )
2013-04-29 00:36:22 +00:00
{
2013-11-22 14:29:11 +00:00
const int bytes = 1 ;
2013-11-25 06:13:32 +00:00
assert ( b ! = NULL ) ;
2013-12-10 06:33:30 +00:00
assert ( offset + bytes < = b - > sizeLimit ) ;
2013-11-22 14:29:11 +00:00
assert ( offset + bytes < = b - > allocSize ) ;
2013-11-25 06:13:32 +00:00
b - > bytes [ offset ] = byte ;
2013-11-22 14:29:11 +00:00
if ( config . debug . overlaybuffer )
2013-12-16 04:49:15 +00:00
DEBUGF ( " ob_set(b=%p, offset=%zd, byte=0x%02x) %p[%zd]=%s " , b , offset , byte , b - > bytes , offset , alloca_tohex ( & b - > bytes [ offset ] , bytes ) ) ;
2013-04-29 00:36:22 +00:00
}
2013-11-22 14:29:11 +00:00
void _ob_patch_rfs ( struct __sourceloc __whence , struct overlay_buffer * b )
2013-11-25 06:13:32 +00:00
{
ob_set_ui16 ( b , b - > var_length_offset , b - > position - ( b - > var_length_offset + 2 ) ) ;
2011-08-17 01:22:17 +00:00
}
2011-09-05 02:49:53 +00:00
2012-11-27 04:02:10 +00:00
2013-12-10 06:33:30 +00:00
size_t ob_position ( struct overlay_buffer * b )
2013-11-25 06:13:32 +00:00
{
2012-11-27 04:02:10 +00:00
return b - > position ;
}
2013-11-25 06:13:32 +00:00
2013-12-10 06:33:30 +00:00
size_t ob_limit ( struct overlay_buffer * b )
2013-11-25 06:13:32 +00:00
{
2012-11-27 04:02:10 +00:00
return b - > sizeLimit ;
}
2013-11-25 06:13:32 +00:00
2013-12-10 06:33:30 +00:00
size_t ob_remaining ( struct overlay_buffer * b )
2013-11-25 06:13:32 +00:00
{
2013-12-10 06:33:30 +00:00
assert ( b - > sizeLimit ! = SIZE_MAX ) ;
assert ( b - > position < = b - > sizeLimit ) ;
return ( size_t ) ( b - > sizeLimit - b - > position ) ;
2012-11-27 04:02:10 +00:00
}
2013-11-25 06:13:32 +00:00
2013-11-22 14:29:11 +00:00
int _ob_overrun ( struct __sourceloc __whence , struct overlay_buffer * b )
2013-11-25 06:13:32 +00:00
{
2013-12-10 06:33:30 +00:00
int ret = b - > position > ( b - > sizeLimit ! = SIZE_MAX & & b - > sizeLimit < b - > allocSize ? b - > sizeLimit : b - > allocSize ) ;
2013-11-22 14:29:11 +00:00
if ( config . debug . overlaybuffer )
DEBUGF ( " ob_overrun(b=%p) return %d " , b , ret ) ;
return ret ;
2013-11-25 06:13:32 +00:00
}
unsigned char * ob_ptr ( struct overlay_buffer * b )
{
2012-11-27 04:02:10 +00:00
return b - > bytes ;
}
2011-09-05 02:49:53 +00:00
int asprintable ( int c )
{
if ( c < ' ' ) return ' . ' ;
if ( c > 0x7e ) return ' . ' ;
return c ;
}
2013-08-30 05:40:54 +00:00
int ob_dump ( struct overlay_buffer * b , char * desc )
2011-09-05 02:49:53 +00:00
{
2013-12-10 06:33:30 +00:00
DEBUGF ( " overlay_buffer '%s' at %p (%p) : position=%zu, size=%zu " , desc , b , b - > bytes , b - > position , b - > sizeLimit ) ;
if ( b - > bytes ) {
if ( b - > sizeLimit ! = SIZE_MAX & & b - > sizeLimit > 0 ) {
assert ( b - > position < = b - > sizeLimit ) ;
dump ( desc , b - > bytes , b - > sizeLimit ) ;
} else if ( b - > position > 0 )
dump ( desc , b - > bytes , b - > position ) ;
}
2011-09-05 02:49:53 +00:00
return 0 ;
}