Commit 5884c9d6 authored by Stephen R. van den Berg's avatar Stephen R. van den Berg

Stdio.Buffer: Protect against calls in destructed Buffer objects.

parent 01543a00
......@@ -887,9 +887,15 @@ PIKECLASS Buffer
}
}
static Buffer* already_destructed() {
Pike_error("Stdio.Buffer already destructed.\n");
return 0;
}
#undef THIS
#define THIS (&(((struct Buffer_struct *)Pike_fp->current_storage)->b))
#define CHECK_DESTRUCTED(io) ((io)->this ? (io) : already_destructed())
/* pike functions */
......@@ -907,7 +913,7 @@ PIKECLASS Buffer
*/
PIKEFUN int(-1..) input_from( object f, int|void _nbytes, int|void _once )
{
Buffer *io = THIS;
Buffer *io = CHECK_DESTRUCTED(THIS);
size_t sz = io_len( io );
size_t bread = 0, nbytes = (size_t)-1;
struct my_file *fd;
......@@ -983,7 +989,7 @@ PIKECLASS Buffer
*/
PIKEFUN void __set_on_write( zero|function f )
{
Buffer *io = THIS;
Buffer *io = CHECK_DESTRUCTED(THIS);
if (f)
assign_svalue(&io->output, f);
......@@ -1031,7 +1037,7 @@ PIKECLASS Buffer
PIKEFUN int(-1..) output_to( object|function(string(8bit):int) f,
int|void nbytes )
{
Buffer *io = THIS;
Buffer *io = CHECK_DESTRUCTED(THIS);
ptrdiff_t written = 0;
ptrdiff_t sz = io_len( io );
int write_fun_num = -1;
......@@ -1119,7 +1125,7 @@ PIKECLASS Buffer
*/
PIKEFUN int read_sint( int nbytes )
{
Buffer *io = THIS;
Buffer *io = CHECK_DESTRUCTED(THIS);
struct pike_string *tmp;
Pike_sp--;
if( !io_avail( io, nbytes ) )
......@@ -1152,7 +1158,7 @@ PIKECLASS Buffer
PIKEFUN int(0..) _size_object( )
{
Buffer *io = THIS;
Buffer *io = CHECK_DESTRUCTED(THIS);
if (io->malloced)
{
push_ulongest(THIS->allocated);
......@@ -1171,7 +1177,7 @@ PIKECLASS Buffer
*/
PIKEFUN Buffer add_padding( int(0..) nbytes, int|void _byte )
{
Buffer *io = THIS;
Buffer *io = CHECK_DESTRUCTED(THIS);
int byte = 0;
if( _byte ) byte = _byte->u.integer;
......@@ -1218,8 +1224,8 @@ PIKECLASS Buffer
*/
PIKEFUN Buffer add( object|string(8bit)|int|array(object|string(8bit)|int) ... argp)
{
Buffer *io = CHECK_DESTRUCTED(THIS);
int i;
Buffer *io = THIS;
for(i=0; i<args; i++ )
io_append_svalue( io, argp+i );
......@@ -1233,7 +1239,7 @@ PIKECLASS Buffer
*/
PIKEFUN Buffer add_int8( int i )
{
Buffer *io = THIS;
Buffer *io = CHECK_DESTRUCTED(THIS);
*io_add_space(io,1,0)=i;
io->len++;
Pike_sp--;
......@@ -1246,8 +1252,8 @@ PIKECLASS Buffer
*/
PIKEFUN Buffer add_int8( object mpz )
{
Buffer *io = CHECK_DESTRUCTED(THIS);
INT64 i = 0;
Buffer *io = THIS;
unsigned char *p = io_add_space(io,1,0);
if (!low_int64_from_bignum(&i, mpz)) {
SIMPLE_ARG_TYPE_ERROR("add_int8", 1, "int|Gmp.mpz");
......@@ -1263,7 +1269,7 @@ PIKECLASS Buffer
*/
PIKEFUN Buffer add_int16( int i )
{
Buffer *io = THIS;
Buffer *io = CHECK_DESTRUCTED(THIS);
unsigned char *p = io_add_space(io,2,0);
p[0] = i>>8;
p[1] = i;
......@@ -1278,8 +1284,8 @@ PIKECLASS Buffer
*/
PIKEFUN Buffer add_int16( object mpz )
{
Buffer *io = CHECK_DESTRUCTED(THIS);
INT64 i = 0;
Buffer *io = THIS;
unsigned char *p = io_add_space(io,2,0);
if (!low_int64_from_bignum(&i, mpz)) {
SIMPLE_ARG_TYPE_ERROR("add_int16", 1, "int|Gmp.mpz");
......@@ -1295,7 +1301,7 @@ PIKECLASS Buffer
*/
PIKEFUN Buffer add_int32( int i )
{
Buffer *io = THIS;
Buffer *io = CHECK_DESTRUCTED(THIS);
unsigned char *p = io_add_space(io,4,0);
p[0] = i>>24;
p[1] = i>>16;
......@@ -1311,8 +1317,8 @@ PIKECLASS Buffer
*/
PIKEFUN Buffer add_int32( object mpz )
{
Buffer *io = CHECK_DESTRUCTED(THIS);
INT64 i = 0;
Buffer *io = THIS;
unsigned char *p = io_add_space(io,4,0);
if (!low_int64_from_bignum(&i, mpz)) {
SIMPLE_ARG_TYPE_ERROR("add_int32", 1, "int|Gmp.mpz");
......@@ -1376,7 +1382,7 @@ PIKECLASS Buffer
int|string(8bit)|object|array(int|string(8bit)|Buffer|array) str,
int size_size, void|int offset )
{
Buffer *io = THIS;
Buffer *io = CHECK_DESTRUCTED(THIS);
size_t len = io_svalue_len(io, str);
if( offset )
......@@ -1402,16 +1408,17 @@ PIKECLASS Buffer
*/
PIKEFUN Buffer add_int( object|int i, int width )
{
Buffer *io = CHECK_DESTRUCTED(THIS);
pop_stack(); /* width */
if( TYPEOF(*i) == PIKE_T_INT )
{
io_add_int( THIS, i->u.integer, width );
io_add_int( io, i->u.integer, width );
Pike_sp--;
}
else
{
convert_stack_top_to_bignum();
io_add_bignum( THIS, i->u.object, width );
io_add_bignum( io, i->u.object, width );
pop_stack(); /* o. */
}
ref_push_object(Pike_fp->current_object);
......@@ -1428,20 +1435,21 @@ PIKECLASS Buffer
*/
PIKEFUN Buffer add_hint( object|int i, int len_width )
{
Buffer *io = CHECK_DESTRUCTED(THIS);
int width;
pop_stack(); /* width */
if( TYPEOF(*i) == PIKE_T_INT )
{
INT_TYPE ui = i->u.integer;
if (!ui) {
io_add_int( THIS, 0, len_width );
io_add_int( io, 0, len_width );
} else {
for( width=1; width<SIZEOF_INT_TYPE; width++ )
if( ui < (((INT_TYPE)1)<<(width*8)) &&
ui >= -(((INT_TYPE)1)<<(width*8-1)) )
break;
io_add_int( THIS, width, len_width );
io_add_int( THIS, i->u.integer, width );
io_add_int( io, width, len_width );
io_add_int( io, i->u.integer, width );
}
Pike_sp--;
}
......@@ -1449,8 +1457,8 @@ PIKECLASS Buffer
{
convert_stack_top_to_bignum();
width = (mpz_sizeinbase( (void*)i->u.object->storage, 2)+7)/8;
io_add_int( THIS, width, len_width );
io_add_bignum( THIS, i->u.object, width );
io_add_int( io, width, len_width );
io_add_bignum( io, i->u.object, width );
pop_stack(); /* o. */
}
ref_push_object(Pike_fp->current_object);
......@@ -1470,12 +1478,12 @@ PIKECLASS Buffer
*/
PIKEFUN Buffer add_ints( array(int) a, int bpi )
{
Buffer *io = CHECK_DESTRUCTED(THIS);
int i,l = a->size;
struct svalue *it = a->item;
unsigned char *ptr;
ptrdiff_t n=0;
ONERROR e;
Buffer *io = THIS;
io_unwrite_on_error(io, &e);
......@@ -1544,7 +1552,7 @@ PIKECLASS Buffer
PIKEFUN int(8bit) `[]( int off )
flags ID_PROTECTED;
{
Buffer *io = THIS;
Buffer *io = CHECK_DESTRUCTED(THIS);
if( off < 0 )
off = io_len(io)-off;
......@@ -1561,7 +1569,7 @@ PIKECLASS Buffer
PIKEFUN void `[]=( int off, int val )
flags ID_PROTECTED;
{
Buffer *io = THIS;
Buffer *io = CHECK_DESTRUCTED(THIS);
io_ensure_malloced( io, 0 );
......@@ -1588,7 +1596,8 @@ PIKECLASS Buffer
PIKEFUN int(0..) _sizeof()
flags ID_PROTECTED;
{
push_ulongest(io_len(THIS));
Buffer *io = CHECK_DESTRUCTED(THIS);
push_ulongest(io_len(io));
}
/*! @decl string(8bit) cast("string")
......@@ -1601,15 +1610,16 @@ PIKECLASS Buffer
PIKEFUN string(8bit) cast(string to)
flags ID_PROTECTED;
{
Buffer *io = CHECK_DESTRUCTED(THIS);
if( to != literal_string_string )
{
push_undefined();
return;
}
if( io_len(THIS) > 0x7fffffff )
if( io_len(io) > 0x7fffffff )
Pike_error("This buffer is too large to convert to a string.\n");
push_string(make_shared_binary_string((void*)io_read_pointer(THIS),
(INT32)io_len(THIS)));
push_string(make_shared_binary_string((void*)io_read_pointer(io),
(INT32)io_len(io)));
}
......@@ -1665,10 +1675,11 @@ PIKECLASS Buffer
*/
PIKEFUN Buffer set_error_mode( int|program m )
{
Buffer *io = CHECK_DESTRUCTED(THIS);
if( TYPEOF(*m) == PIKE_T_INT )
io_set_error_mode( THIS, m->u.integer ? buffer_error_program : 0 );
io_set_error_mode( io, m->u.integer ? buffer_error_program : 0 );
else
io_set_error_mode( THIS, program_from_svalue(m));
io_set_error_mode( io, program_from_svalue(m));
pop_stack();
ref_push_object(Pike_fp->current_object);
......@@ -1683,12 +1694,14 @@ PIKECLASS Buffer
*/
PIKEFUN Buffer lock()
{
push_object( io_read_buffer( THIS, 0, 0 ) );
Buffer *io = CHECK_DESTRUCTED(THIS);
push_object( io_read_buffer( io, 0, 0 ) );
}
PIKEFUN string(8bit) _sprintf(int o, mapping|void UNUSED)
flags ID_PROTECTED;
{
Buffer *io = CHECK_DESTRUCTED(THIS);
size_t bytes;
pop_n_elems(args-1);
Pike_sp--;
......@@ -1699,15 +1712,15 @@ PIKECLASS Buffer
push_static_text("%O(%d bytes, read=[..%d] data=[%d..%d] free=[%d..%d] %s%s)");
ref_push_program(Pike_fp->current_object->prog);
/* io_len [..offset] [offset..len] [..allocated] */
push_int(io_len(THIS));
push_int(THIS->offset-1);
push_int(THIS->offset);
push_int(THIS->len-1);
push_int(THIS->len);
push_int(THIS->allocated);
push_static_text( (THIS->str ? "string" : THIS->malloced ? "allocated" : "subbuffer" ) );
if( THIS->locked )
push_int(io_len(io));
push_int(io->offset-1);
push_int(io->offset);
push_int(io->len-1);
push_int(io->len);
push_int(io->allocated);
push_static_text( (io->str ? "string" : io->malloced ? "allocated" : "subbuffer" ) );
if( io->locked )
push_static_text(" (read only)");
else
push_static_text("");
......@@ -1716,20 +1729,20 @@ PIKECLASS Buffer
break;
case 's':
bytes = io_len(THIS);
THIS->locked_move++;
push_string( io_read_string(THIS, bytes) );
io_rewind(THIS, bytes);
THIS->locked_move--;
bytes = io_len(io);
io->locked_move++;
push_string( io_read_string(io, bytes) );
io_rewind(io, bytes);
io->locked_move--;
break;
case 'q':
push_static_text("%q");
bytes = io_len(THIS);
THIS->locked_move++;
push_string( io_read_string(THIS, bytes) );
io_rewind(THIS, bytes);
THIS->locked_move--;
bytes = io_len(io);
io->locked_move++;
push_string( io_read_string(io, bytes) );
io_rewind(io, bytes);
io->locked_move--;
f_sprintf(2);
break;
default:
......@@ -1755,8 +1768,8 @@ PIKECLASS Buffer
*/
PIKEFUN string(8bit) read_hstring( int bytes, void|int offset )
{
Buffer *io = CHECK_DESTRUCTED(THIS);
INT64 len;
Buffer *io = THIS;
struct pike_string *s;
ONERROR e;
......@@ -1813,7 +1826,7 @@ PIKECLASS Buffer
PIKEFUN string(8bit) read_cstring(void|int(8bit) sentinel,
void|int(8bit) escape)
{
Buffer *io = THIS;
Buffer *io = CHECK_DESTRUCTED(THIS);
int csentinel = sentinel ? sentinel->u.integer : 0;
if (!escape || (escape->u.integer == csentinel)) {
......@@ -1901,7 +1914,7 @@ PIKECLASS Buffer
rawtype tFunc(tInt8bit tOr(tInt, tVoid) tOr(tIntPos, tVoid),
tOr(tInt_10, tIntPos));
{
Buffer *io = THIS;
Buffer *io = CHECK_DESTRUCTED(THIS);
unsigned char *buf = io_read_pointer(io);
unsigned char *buf_end = buf + io_len(io);
......@@ -1971,7 +1984,7 @@ PIKECLASS Buffer
PIKEFUN int _search(string(8bit) substring, int|void start, int|void end)
flags ID_PROTECTED;
{
Buffer *io = THIS;
Buffer *io = CHECK_DESTRUCTED(THIS);
unsigned char *buf = io_read_pointer(io);
unsigned char *buf_end = buf + io_len(io);
SearchMojt mojt;
......@@ -2046,9 +2059,9 @@ PIKECLASS Buffer
*/
PIKEFUN Buffer read_hbuffer( int bytes, int|void copy )
{
Buffer *io = CHECK_DESTRUCTED(THIS);
INT64 len;
int do_copy = 0;
Buffer *io = THIS;
ONERROR e;
io_rewind_on_error( io, &e );
......@@ -2084,12 +2097,13 @@ PIKECLASS Buffer
*/
PIKEFUN Buffer read_buffer( int bytes, int|void copy )
{
Buffer *io = CHECK_DESTRUCTED(THIS);
int do_copy = 0;
struct object *o;
if( copy )
do_copy = copy->u.integer;
Pike_sp-=args;
if( (o = io_read_buffer( THIS, bytes, do_copy )) )
if( (o = io_read_buffer( io, bytes, do_copy )) )
push_object(o);
else
push_int(0);
......@@ -2106,6 +2120,7 @@ PIKECLASS Buffer
rawtype tFuncV(tAttr("strict_sprintf_format", tOr(tStr, tObj)),
tAttr("sprintf_args", tMix), tObjIs_BUFFER);
{
Buffer *io = CHECK_DESTRUCTED(THIS);
ONERROR _e;
struct string_builder tmp;
init_string_builder(&tmp,0);
......@@ -2113,7 +2128,7 @@ PIKECLASS Buffer
low_f_sprintf(args, &tmp);
if( tmp.s->size_shift )
Pike_error("Buffer only handles 8bit data.\n");
io_append( THIS, tmp.s->str, tmp.s->len );
io_append( io, tmp.s->str, tmp.s->len );
pop_n_elems(args);
CALL_AND_UNSET_ONERROR(_e);
ref_push_object(Pike_fp->current_object);
......@@ -2130,25 +2145,26 @@ PIKECLASS Buffer
*/
PIKEFUN array sscanf( string(8bit) format )
{
Buffer *io = CHECK_DESTRUCTED(THIS);
INT32 i;
ptrdiff_t num_used;
struct svalue *start = Pike_sp;
retry:
i = low_sscanf_pcharp(
MKPCHARP(io_read_pointer(THIS), 0), io_len(THIS),
MKPCHARP(io_read_pointer(io), 0), io_len(io),
MKPCHARP(format->str,format->size_shift), format->len,
&num_used);
if( !num_used )
{
if( io_range_error(THIS,0) )
if( io_range_error(io,0) )
goto retry;
pop_n_elems(Pike_sp-start);
push_int(0);
}
else
{
io_consume( THIS, num_used );
io_consume( io, num_used );
f_aggregate(Pike_sp-start);
}
}
......@@ -2176,6 +2192,7 @@ PIKECLASS Buffer
*/
PIKEFUN mixed read_json(int|void require_whitespace)
{
Buffer *io = CHECK_DESTRUCTED(THIS);
INT_TYPE whites = 0;
ptrdiff_t stop;
static ptrdiff_t(*parse_json_pcharp)(PCHARP,size_t,int,char**);
......@@ -2187,14 +2204,14 @@ PIKECLASS Buffer
if( !parse_json_pcharp )
parse_json_pcharp = PIKE_MODULE_IMPORT(Standards.JSON, parse_json_pcharp );
retry:
stop = parse_json_pcharp( MKPCHARP(io_read_pointer(THIS),0),
io_len(THIS), 1|8, &err ); /* json_utf8 */
stop = parse_json_pcharp( MKPCHARP(io_read_pointer(io),0),
io_len(io), 1|8, &err ); /* json_utf8 */
if( stop < 0 )
{
if( -stop == (ptrdiff_t)io_len(THIS) || (err && !strncmp(err,"Unterminated",12)))
if( -stop == (ptrdiff_t)io_len(io) || (err && !strncmp(err,"Unterminated",12)))
{
if( io_range_error(THIS,0) )
if( io_range_error(io,0) )
goto retry;
push_undefined();
}
......@@ -2210,11 +2227,11 @@ PIKECLASS Buffer
else
{
if( whites &&
(io_is_whitespace(THIS,stop)<=0 && io_is_whitespace(THIS,stop-1)<=0))
(io_is_whitespace(io,stop)<=0 && io_is_whitespace(io,stop-1)<=0))
{
if( stop == (ptrdiff_t)io_len(THIS) )
if( stop == (ptrdiff_t)io_len(io) )
{
if( io_range_error(THIS,0) )
if( io_range_error(io,0) )
goto retry;
pop_stack();
push_undefined();
......@@ -2225,9 +2242,9 @@ PIKECLASS Buffer
else
{
if( whites )
while( io_is_whitespace( THIS, stop ) )
while( io_is_whitespace( io, stop ) )
stop++;
io_consume( THIS, stop );
io_consume( io, stop );
}
}
}
......@@ -2251,25 +2268,26 @@ PIKECLASS Buffer
*/
PIKEFUN string(8bit)|int|float|array match( string(8bit) format )
{
Buffer *io = CHECK_DESTRUCTED(THIS);
INT32 i;
ptrdiff_t num_used;
struct svalue *start = Pike_sp;
retry:
i = low_sscanf_pcharp(
MKPCHARP(io_read_pointer(THIS), 0), io_len(THIS),
MKPCHARP(io_read_pointer(io), 0), io_len(io),
MKPCHARP(format->str,format->size_shift), format->len,
&num_used);
if( !num_used )
{
if( io_range_error(THIS,0) )
if( io_range_error(io,0) )
goto retry;
pop_n_elems(Pike_sp-start);
push_int(0);
}
else
{
io_consume( THIS, num_used );
io_consume( io, num_used );
if( Pike_sp-start > 1 )
f_add(Pike_sp-start);
}
......@@ -2281,7 +2299,7 @@ PIKECLASS Buffer
*/
PIKEFUN void clear( )
{
Buffer *io = THIS;
Buffer *io = CHECK_DESTRUCTED(THIS);
io->offset = io->len = 0;
}
......@@ -2295,7 +2313,7 @@ PIKECLASS Buffer
*/
PIKEFUN void set_max_waste(float howmuch)
{
Buffer *io = THIS;
Buffer *io = CHECK_DESTRUCTED(THIS);
io->max_waste = howmuch;
io_add_space( io, 0, 1 );
io_trim_waste( io );
......@@ -2314,7 +2332,7 @@ PIKECLASS Buffer
*/
PIKEFUN void trim( )
{
Buffer *io = THIS;
Buffer *io = CHECK_DESTRUCTED(THIS);
io_add_space( io, 0, 1 );
io_trim(io);
......@@ -2326,7 +2344,7 @@ PIKECLASS Buffer
*/
PIKEFUN void allocate( int n )
{
Buffer *io = THIS;
Buffer *io = CHECK_DESTRUCTED(THIS);
Pike_sp--;
if (!n) return;
if (n < 0)
......@@ -2342,11 +2360,12 @@ PIKECLASS Buffer
*/
PIKEFUN int(-1..) consume( int n )
{
Buffer *io = CHECK_DESTRUCTED(THIS);
Pike_sp--;
if( !io_avail( THIS, n ) )
if( !io_avail( io, n ) )
push_int(-1);
else
push_int64( io_consume( THIS, n ) );
push_int64( io_consume( io, n ) );
}
/*! @decl int(0..)|int(-1..-1) truncate( int(0..) n )
......@@ -2357,7 +2376,7 @@ PIKECLASS Buffer
*/
PIKEFUN int(-1..) truncate( int(0..) n )
{
Buffer *io = THIS;
Buffer *io = CHECK_DESTRUCTED(THIS);
ptrdiff_t diff = io_len(io) - n;
Pike_sp--;
......@@ -2387,8 +2406,9 @@ PIKECLASS Buffer
*/
PIKEFUN int(-1..) unread( int bytes )
{
Buffer *io = CHECK_DESTRUCTED(THIS);
Pike_sp--;
push_int64( io_rewind( THIS, bytes ) );
push_int64( io_rewind( io, bytes ) );
}
/*! @decl string(8bit) read( int n )
......@@ -2402,9 +2422,10 @@ PIKECLASS Buffer
*/
PIKEFUN string(8bit) read( int bytes )
{
Buffer *io = CHECK_DESTRUCTED(THIS);
struct pike_string *s;
Pike_sp--;
s = io_read_string(THIS, bytes );
s = io_read_string(io, bytes );
if( s )
push_string( s );
else
......@@ -2425,7 +2446,8 @@ PIKECLASS Buffer
*/
PIKEFUN string(8bit) read()
{
push_string( io_read_string(THIS, io_len(THIS)) );
Buffer *io = CHECK_DESTRUCTED(THIS);
push_string( io_read_string(io, io_len(io)) );
}
/*! @decl string(8bit) try_read(int len)
......@@ -2445,20 +2467,20 @@ PIKECLASS Buffer
*/
PIKEFUN string(8bit) try_read( int bytes )
{
Buffer *this = THIS;
Buffer *io = CHECK_DESTRUCTED(THIS);
struct pike_string *s;
Pike_sp--;
/* Hm. signed/unsigned comparisons abound. */
if( bytes > 0 && (size_t)bytes > io_len(this) )
bytes = io_len(this);
push_string( io_read_string(this, bytes ) );
if( bytes > 0 && (size_t)bytes > io_len(io) )
bytes = io_len(io);
push_string( io_read_string(io, bytes ) );
}
/*! @decl int(8bit) read_int8()
*/
PIKEFUN int(8bit) read_int8( )
{
Buffer *io = THIS;
Buffer *io = CHECK_DESTRUCTED(THIS);
if( LIKELY(io_avail( io, 1 )) )
push_int( io_read_byte_uc(io) );
else
......@@ -2469,7 +2491,7 @@ PIKECLASS Buffer
*/