ouch - bad call of MKSTRING_L passing a pointer into object memory
authorClaus Gittinger <cg@exept.de>
Mon, 09 Mar 2015 18:46:37 +0100
changeset 17597 a78c4a2bf366
parent 17596 082b7d32692a
child 17598 7618f46602ea
ouch - bad call of MKSTRING_L passing a pointer into object memory
ReadStream.st
--- a/ReadStream.st	Mon Mar 09 18:46:04 2015 +0100
+++ b/ReadStream.st	Mon Mar 09 18:46:37 2015 +0100
@@ -18,6 +18,22 @@
 	category:'Streams'
 !
 
+!ReadStream primitiveDefinitions!
+%{
+
+#include <stdio.h>
+#define _STDIO_H_INCLUDED_
+#include <stdlib.h>
+#include <string.h>
+#include <memory.h>
+#ifdef __osx__
+// missing definition ?
+extern void *memchr( void *, int, size_t);
+#endif
+
+%}
+! !
+
 !ReadStream class methodsFor:'documentation'!
 
 copyright
@@ -246,7 +262,9 @@
 
     INT pos, limit, sz;
     INT len;
-    char buffer[256];
+    char quickBuffer[256];
+    char *buffer = quickBuffer;
+    int bufferSize = sizeof(quickBuffer);
     REGISTER unsigned char *cp;
     REGISTER unsigned ch;
     OBJ coll, p, l;
@@ -256,6 +274,7 @@
     l = __INST(readLimit);
 
     if (__isStringLike(coll) && __bothSmallInteger(p, l)) {
+	OBJ retVal;
 
 	pos = __intVal(p);
 	/* make 1-based */
@@ -267,6 +286,7 @@
 	    limit = sz;
 	cp = __stringVal(coll) + pos - 1;
 
+	/* skip over non-alphanumeric characters */
 	for (;;) {
 	    if (pos > limit) break;
 	    ch = *cp;
@@ -279,6 +299,7 @@
 	    pos++;
 	}
 
+	/* collect non-alphanumeric characters */
 	len = 0;
 	for (;;) {
 	    if (pos > limit) break;
@@ -289,9 +310,16 @@
 		   ((ch >= '0') && (ch <= '9'))))
 		break;
 	    buffer[len++] = ch;
-	    if (len >= (sizeof(buffer)-1)) {
-		/* emergency */
-		break;
+	    if (len >= (bufferSize-1)) {
+		int newBufferSize = bufferSize * 2;
+
+		if (buffer == quickBuffer) {
+		    buffer = (char *)malloc(newBufferSize);
+		    memcpy(buffer, quickBuffer, bufferSize);
+		} else {
+		    buffer = (char *)realloc(buffer, newBufferSize);
+		}
+		bufferSize = newBufferSize;
 	    }
 	    pos++;
 	    cp++;
@@ -300,7 +328,14 @@
 	pos = pos - 1;
 	__INST(position) = __mkSmallInteger(pos);
 	buffer[len] = '\0';
-	RETURN ( (len != 0) ? __MKSTRING_L(buffer, len) : nil );
+	if (len == 0) {
+	    RETURN (nil);
+	}
+	retVal = __MKSTRING_L(buffer, len);
+	if (buffer != quickBuffer) {
+	    free((void *)buffer);
+	}
+	RETURN ( retVal );
     }
 %}
 .
@@ -834,15 +869,13 @@
 	unsigned int ch = __intVal(__characterVal(anObject));
 
 	if (ch <= 0xFF) {
-	    INT _startPos = __intVal(__INST(position));
-	    INT _endIndex;
+	    int _startPos = __intVal(__INST(position));
+	    int _endIndex;
 	    char *startPtr = __stringVal(_collection) + _startPos;
 	    char *foundPtr;
 	    OBJ rslt;
-	    INT nMax;
-#ifdef __osx__
-	    extern char*memchr(char *, int, long);
-#endif
+	    int nMax;
+
 	    _endIndex = __stringSize(_collection);
 	    if (__isInteger(__INST(readLimit))) {
 		int _readLimit = __intVal(__INST(readLimit));
@@ -851,16 +884,22 @@
 	    }
 
 	    nMax = _endIndex-_startPos;
-	    foundPtr = memchr( startPtr, ch, (long)nMax);
+	    foundPtr = (char *)memchr( startPtr, ch, (long)nMax);
 	    if (foundPtr == 0) {
 		// not found
-		rslt = __MKSTRING_L(startPtr, nMax);
+		rslt = __MKEMPTYSTRING(nMax);
+		// refetch - may GC
+		_collection = __INST(collection);
+		memcpy((void *)__stringVal(rslt), (void *)(__stringVal(_collection) + _startPos), (size_t)nMax);
 		__INST(position) = __mkSmallInteger(_endIndex);
 	    } else {
-		INT n = foundPtr-startPtr;
+		// found at foundPtr
+		int n = foundPtr-startPtr;
 
-		// found at foundPtr
-		rslt = __MKSTRING_L(startPtr, n);
+		rslt = __MKEMPTYSTRING(n);
+		// refetch - may GC
+		_collection = __INST(collection);
+		memcpy((void *)__stringVal(rslt), (void *)(__stringVal(_collection) + _startPos), (size_t)n);
 		__INST(position) = __mkSmallInteger(_startPos + n + 1);
 	    }
 	    RETURN (rslt);
@@ -881,9 +920,9 @@
 !ReadStream class methodsFor:'documentation'!
 
 version
-    ^ '$Header: /cvs/stx/stx/libbasic/ReadStream.st,v 1.78 2014-10-04 20:33:07 cg Exp $'
+    ^ '$Header: /cvs/stx/stx/libbasic/ReadStream.st,v 1.79 2015-03-09 17:46:37 cg Exp $'
 !
 
 version_CVS
-    ^ '$Header: /cvs/stx/stx/libbasic/ReadStream.st,v 1.78 2014-10-04 20:33:07 cg Exp $'
+    ^ '$Header: /cvs/stx/stx/libbasic/ReadStream.st,v 1.79 2015-03-09 17:46:37 cg Exp $'
 ! !