From 0da32f28029fcdda90f4726269dfba760a5bc415 Mon Sep 17 00:00:00 2001 From: "Stephen R. van den Berg" <srb@cuci.nl> Date: Thu, 17 May 2018 17:16:45 +0200 Subject: [PATCH] Stdio.Buffer: Eliminates race condition from read_cstring(). In addition it makes read_cstring(): - Restartable after buffer changes from range_error(). - Call range_error(0) just like sscanf(). - Faster. The race condition occurred after a pause due to range_error(), the subsequent io_rewind() at the end could not rewind far enough. --- src/modules/_Stdio/buffer.cmod | 40 +++++++++++----------------------- 1 file changed, 13 insertions(+), 27 deletions(-) diff --git a/src/modules/_Stdio/buffer.cmod b/src/modules/_Stdio/buffer.cmod index 43a86025f2..d0ad267e47 100644 --- a/src/modules/_Stdio/buffer.cmod +++ b/src/modules/_Stdio/buffer.cmod @@ -1783,39 +1783,25 @@ PIKECLASS Buffer *! *! Note that pike string can not be longer than 0x7fffffff bytes (~2Gb). */ - PIKEFUN string(0..255) read_cstring( ) + PIKEFUN string(0..255) read_cstring() { - LONGEST len; Buffer *io = THIS; - struct pike_string *s; - ONERROR e; - io_rewind_on_error( io, &e ); - len = 0; - do { - /* search the amount of data we know we have for each call to io_avail */ - while( io_len(io) ) + do + if ( LIKELY(io_len(THIS)) ) { - if( !io_read_byte_uc(io) ) - goto found_null; - len++; + const char * start = io_read_pointer(io); + const char * end = memchr(start, 0, io_len(io)); + if ( LIKELY(end) ) + { + push_string(io_read_string(io, end - start)); + io_read_byte_uc(io); /* consume the terminating \0 byte */ + return; + } } - } - while( io_avail( io, 1 ) ); - goto fail; + while ( UNLIKELY(io_range_error(THIS, 0)) ); - found_null: - io_rewind( io, len+1 ); - s = io_read_string( io, len ); - - if( LIKELY(s) ) { - io_read_byte_uc(io); /* consume the terminating \0 byte */ - io_unset_rewind_on_error( io, &e ); - push_string(s); - } else { -fail: CALL_AND_UNSET_ONERROR(e); - push_undefined(); - } + push_undefined(); } /*! @decl Buffer read_hbuffer( int n ) -- GitLab