aboutsummaryrefslogtreecommitdiff
path: root/src/SString.c
diff options
context:
space:
mode:
authorswhite <swhite@1faa4e14-9dd3-4be0-9f0e-ffe519881164>2004-04-06 17:45:14 +0000
committerswhite <swhite@1faa4e14-9dd3-4be0-9f0e-ffe519881164>2004-04-06 17:45:14 +0000
commit89b88d27b20641e04cd1c2714c299d8908822b54 (patch)
tree5b31770e8864f4d6f0953acbe24af5cc80d43730 /src/SString.c
parent3ccc27cd1bf0912054213a88798b088010173f1e (diff)
Regarding Cactus bug report 1632 "HTTPD contains buffer overflows"
1) Got rid of most strcat/sprintf into automatic array, replaced with a String module that allocates dynamic memory on the heap. 2) Went a long way toward initializing all variables. 3) Tested: Ran two copies with same parfile except different port, one with my changes, one with original. Went through different kinds of pages by hand, checked by eye. 4) Tried to make HTML XHTML 1.0-compliant. Checked with Amaya. One problem: How to deal with raw less-than characters, etc. Made a function to convert them to HTML Character Entities, but isn't clear this will work properly in the forms. So I left these symbols in the forms. 5) Also checked with more primitive browsers, lynx and dillo. 6) Marked a few instances of questionable code with 'SW' To do ----- Document a few new functions, esp. in Content.c git-svn-id: http://svn.cactuscode.org/arrangements/CactusConnect/HTTPD/trunk@187 1faa4e14-9dd3-4be0-9f0e-ffe519881164
Diffstat (limited to 'src/SString.c')
-rw-r--r--src/SString.c442
1 files changed, 442 insertions, 0 deletions
diff --git a/src/SString.c b/src/SString.c
new file mode 100644
index 0000000..bf7c953
--- /dev/null
+++ b/src/SString.c
@@ -0,0 +1,442 @@
+ /*@@
+ @file SString.c
+ @date 02.04.2004
+ @author Steve White
+ @desc Module for generic operations on strings
+ @enddesc
+ @version $Header$
+ @@*/
+
+#include "SString.h"
+#include "SStringIO.h"
+
+#include <string.h>
+#include <stdlib.h>
+
+#ifndef MIN
+#define MIN( a, b ) ( (a) < (b) ? (a) : (b) )
+#endif
+#ifndef MAX
+#define MAX( a, b ) ( (a) > (b) ? (a) : (b) )
+#endif
+
+typedef enum { MAKE_NULL_ALLOC, NEW_NULL_ALLOC, BUFFER_NULL_ALLOC }
+SSTRING_ERROR;
+static void String_HandleSeriousError( SSTRING_ERROR );
+
+typedef struct String_tag
+{
+ size_t length;
+ SSCHAR *chars;
+} String_placeholder;
+
+static SSCHAR kLineEndChar = '\n';
+
+static SSBOOL BufferForThisManyChars( String *s, size_t size );
+
+size_t
+StringLength( const String * s )
+{
+ return s->length;
+}
+
+const SSCHAR *
+StringGetBuffer( const String * s )
+{
+ return s->chars;
+}
+/*
+ * Returns 0 if index is not in the string
+ */
+SSCHAR
+StringNthChar( const String * s, size_t n )
+{
+ if( n < s->length )
+ return s->chars[n];
+ else
+ return '\0';
+}
+
+String *
+String_New()
+{
+ String *s = (String *)calloc( 1, sizeof( String ) );
+ if( s != NULL )
+ BufferForThisManyChars( s, 0 );
+ else
+ String_HandleSeriousError( NEW_NULL_ALLOC );
+
+ return s;
+}
+
+String *
+String_Make( const SSCHAR * c_string )
+{
+ String *s = (String *)calloc( 1, sizeof( String ) );
+ if( s != NULL )
+ {
+ if( c_string != NULL )
+ {
+ size_t len = strlen( c_string );
+ s->chars = strdup( c_string );
+ s->length = len;
+ }
+ else
+ BufferForThisManyChars( s, 0 );
+ }
+ else
+ String_HandleSeriousError( MAKE_NULL_ALLOC );
+ return s;
+}
+
+/* note this is a little ambiguous.
+ * needs to be made clear this makes a new string
+ */
+String *
+String_Copy( const String * other )
+{
+ return StringSetToCString( String_New(), StringGetBuffer( other ) );
+}
+
+void
+String_Delete( String * s )
+{
+ if( s != NULL )
+ free( s->chars );
+ free( s );
+}
+
+String *
+StringTruncate( String * s, size_t n )
+{
+ if( n < s->length )
+ {
+ s->chars[n] = '\0';
+ s->length = n;
+ }
+ return s;
+}
+
+String *
+StringSetNthChar( String * s, size_t n, SSCHAR c )
+{
+ if( n < s->length )
+ {
+ if( c == '\0' )
+ StringTruncate( s, n );
+ else
+ s->chars[n] = c;
+ }
+ return s;
+}
+/* Allocates if there is no buffer
+ * Re-allocates (without changing remaining string) if there is a buffer
+ * Puts a null char at the location of the corresponding size
+ * DOES NOT pad with zeros, or initialize the buffer beyond this
+ */
+SSBOOL
+BufferForThisManyChars( String *s, size_t size )
+{
+ const size_t blocksize = sizeof( SSCHAR ) * ( size + 1 );
+
+ if( s->chars == NULL )
+ s->chars = (SSCHAR *)malloc( blocksize );
+ else if( s->length < size )
+ s->chars = (SSCHAR *)realloc( s->chars, blocksize );
+ else if( s->length > ( size << 1 ) ) /* Don't resize if larger
+ but in ballpark */
+ {
+ s->length = 0;
+ s->chars = (SSCHAR *)malloc( blocksize );
+ }
+
+ if( s->chars != NULL )
+ {
+ s->length = size;
+ if( s->chars != NULL )
+ s->chars[size] = '\0';
+ }
+ else
+ String_HandleSeriousError( BUFFER_NULL_ALLOC );
+
+ return s->chars != NULL;
+}
+
+String *
+StringSetToCString( String * s, const SSCHAR *c_string )
+{
+ return StringSetToBuffer( s, c_string, strlen( c_string ) );
+}
+
+String *
+StringConcatCString( String * s, const SSCHAR *c_string )
+{
+ const size_t orig_len = s->length;
+ if( BufferForThisManyChars( s, orig_len + strlen( c_string ) ) )
+ {
+ strcpy( s->chars + orig_len, c_string );
+ }
+ return s;
+}
+
+String *
+StringSetToBuffer( String * s, const SSCHAR *buf, size_t len )
+{
+ if( s != NULL && buf != NULL )
+ {
+ if( BufferForThisManyChars( s, len ) )
+ {
+ strncpy( s->chars, buf, len );
+ s->chars[ len ] = '\0';
+ }
+ }
+ return s;
+}
+
+String *
+StringSet( String * s, const String * other )
+{
+ return StringSetToCString( s, StringGetBuffer( other ) );
+}
+
+String *
+StringSetSubString( String * s, const String * other,
+ size_t first, size_t last )
+{
+ const size_t other_length = other->length;
+ const size_t veryFirst = MIN( MIN( first, last ), other_length ),
+ veryLast = MIN( MAX( first, last ), other_length ),
+ length = ( veryLast + 1 ) - veryFirst;
+
+ return StringSetToBuffer( s, other->chars + veryFirst, length );
+}
+
+/*
+ * Last argument 'position' is both input and output.
+ * Specifies where to begin search: pass 0 to search whole string
+ * On output, is position where char was found.
+ */
+SSBOOL
+StringFindChar( const String *s, SSCHAR theChar, size_t * position )
+{
+ SSCHAR * charPtr;
+
+ if( s->length > 0
+ && position
+ && *position < s->length
+ && ( charPtr = (SSCHAR *)strchr( s->chars + *position, theChar ) )
+ != NULL )
+ {
+ *position = ( charPtr - s->chars ) / sizeof( SSCHAR );
+ return TRUE;
+ }
+ return FALSE;
+}
+
+SSBOOL
+StringFindSubString( const String * s, const String * other,
+ size_t * position )
+{
+ SSCHAR * charPtr;
+
+ if( s->length >= other->length
+ && position
+ && *position < s->length
+ && s->length > 0
+ && other->length > 0
+ && ( charPtr = (SSCHAR *)strstr( s->chars + *position, other->chars ) )
+ != NULL )
+ {
+ *position = ( charPtr - s->chars ) / sizeof( SSCHAR );
+ return TRUE;
+ }
+ return FALSE;
+}
+
+SSBOOL
+StringEquals( const String * a, const String * b )
+{
+ if( a->length > 0 )
+ return strncmp( a->chars, b->chars, a->length ) == 0;
+ else if( b->length == 0 )
+ return TRUE;
+
+ return FALSE;
+}
+
+int
+StringCompare( const String * a, const String * b )
+{
+ const size_t length = MIN( a->length, b->length );
+
+ if( length > 0 )
+ return strncmp( a->chars, b->chars, length ) <= 0;
+ else if( b->chars == 0 )
+ return TRUE;
+
+ return FALSE;
+}
+
+String *
+StringInsert( String * s, const String * other, size_t position )
+{
+ const size_t oldLength = s->length, otherLength = other->length;
+ String *old = String_Copy( s );
+
+ if( otherLength > 0
+ && position <= oldLength
+ && BufferForThisManyChars( s, oldLength + otherLength ) )
+ {
+ if( position != 0 )
+ strncpy( s->chars, old->chars, position );
+
+ strncpy( s->chars + position, other->chars, otherLength );
+
+ if( position < oldLength )
+ strncpy( s->chars + position + otherLength,
+ old->chars + position, oldLength - position );
+ s->chars[s->length] = '\0';
+ }
+ String_Delete( old );
+
+ return s;
+}
+
+String *
+StringInsertCString( String * s, const char * c_string, size_t position )
+{
+ String *other = String_Make( c_string );
+ StringInsert( s, other, position );
+ String_Delete( other );
+ return s;
+}
+/*
+ * What to do if position is off end of string? We do nothing
+ */
+String *
+StringInsertChar( String * s, SSCHAR c, size_t position )
+{
+ if( position <= s->length )
+ {
+ BufferForThisManyChars( s, s->length + 1 );
+ if( position + 2 < s->length )
+ {
+ s->chars[s->length] = '\0';
+ memmove( s->chars + position + 1, s->chars + position,
+ s->length - 1 - position );
+ s->chars[position] = c;
+ }
+ }
+ return s;
+}
+
+String *
+StringDeleteChar( String * s, size_t position )
+{
+ return StringDeleteRange( s, position, position );
+}
+
+String *
+StringDeleteRange( String * s, size_t begin, size_t end )
+{
+ if( begin <= end && end < s->length )
+ {
+ if( end + 1 < s->length )
+ {
+ memmove( s->chars + begin, s->chars + end + 1,
+ ( s->length - end ) - 1 );
+ }
+ s->length -= end - begin;
+ s->chars[s->length] = '\0';
+ }
+ return s;
+}
+
+String *
+StringConcat( String * s, const String * other )
+{
+ return StringInsert( s, other, s->length );
+}
+
+/*
+ * On unix the default \n works; on the Mac, you might want \r
+ */
+void
+String_SetLineEndCharacter( SSCHAR c )
+{
+ kLineEndChar = c;
+}
+
+String *
+StringReadToEndOfLine( String * s, FILE * file )
+{
+ return StringReadToDelimiter( s, file, kLineEndChar );
+}
+
+String *
+StringReadToDelimiter( String * s, FILE * file, SSCHAR delim )
+{
+ int next;
+
+ while( ( next = fgetc( file ) ) != EOF
+ && (SSCHAR)next != delim )
+ StringInsertChar( s, (SSCHAR)next, s->length );
+
+ return s;
+}
+
+void
+StringPrint( const String * s )
+{
+ fprintf( stdout, "%s", s->chars );
+}
+
+void
+StringPrintToFile( const String * s, FILE * file )
+{
+ fprintf( file, "%s", s->chars );
+}
+
+void
+StringFormatPrint( const String * s, const SSCHAR *format )
+{
+ fprintf( stdout, format, s->chars );
+}
+
+void
+StringFormatPrintToFile( const String * s, const SSCHAR *format, FILE * file )
+{
+ fprintf( file, format, s->chars );
+}
+
+#define DECIMALBUFSIZE 64
+String *
+StringConcatDecimal( String * s, long d )
+{
+ char buf[DECIMALBUFSIZE] = { '\0' };
+ snprintf( buf, sizeof( buf ), "%ld", d );
+ return StringConcatCString( s, buf );
+}
+
+String *
+StringConcatDouble( String * s, double d )
+{
+ char buf[DECIMALBUFSIZE] = { '\0' };
+ snprintf( buf, sizeof( buf ), "%f", d );
+ return StringConcatCString( s, buf );
+}
+
+String *
+StringConcatFormattedDouble( String * s, int ndigits, int ndec, double d )
+{
+ char buf[DECIMALBUFSIZE] = { '\0' };
+ snprintf( buf, sizeof( buf ), "%*.*f", ndigits, ndec, d );
+ return StringConcatCString( s, buf );
+}
+
+void
+String_HandleSeriousError( SSTRING_ERROR e )
+{
+ /* to be filled in on a per-implementation basis */
+}
+