Package: kaya
Version: 0.2.0-5
Severity: grave
Tags: security patch
Justification: user security hole


Kaya 0.2.4 fixes some data loss bugs and security problems (one buffer
overflow, one cross-site scripting and data leak) in the standard
library. Since it is too late in the Etch release cycle to package
0.2.4, the attached patches should fix the problems for 0.2.0 (only four
functions in two files are affected)

Thanks for your work in packaging Kaya for Debian

-- System Information:
Debian Release: 4.0
  APT prefers unstable
  APT policy: (500, 'unstable')
Architecture: i386 (i686)
Shell:  /bin/sh linked to /bin/bash
Kernel: Linux 2.4.27
Locale: LANG=en_GB.UTF-8, LC_CTYPE=en_GB.UTF-8 (charmap=UTF-8)
--- rts/stdfuns.cc	2006-06-27 10:29:33.000000000 +0100
+++ rts/stdfuns.cc.new	2007-01-29 18:45:57.000000000 +0000
@@ -45,6 +45,9 @@
 #include "VMState.h"
 #include "KayaAPI.h"
 
+// Read lines from files this many characters at a time
+#define LINE_CHUNK 1024
+
 KayaArray args;
 ArgMap httpargs;
 
@@ -117,20 +120,80 @@
 
 wchar_t* getLine(FILE* f)
 {
-// I know there's a better way. Can't be bothered.
-    char* buf=(char*)GC_MALLOC_ATOMIC(4096*sizeof(char)); 
-    fgets(buf,4096,f);
-    return strtowc(buf);    
+    unsigned size = LINE_CHUNK; // #define at top of file
+    // buffer to read into
+    char* buf=(char*)GC_MALLOC_ATOMIC(LINE_CHUNK*sizeof(char)+1); 
+    // accumulator for result; but only allocate it when it turns out to be
+    // needed (i.e., when one chunk isn't enough).
+    char* res=NULL;
+    char* r;
+    do {
+	r = fgets(buf,LINE_CHUNK,f);
+	if (r == NULL) { // End of file, or read error. FIXME: Check which.
+	    if (res==NULL)
+	    {
+		// Fail silently (should this throw an exception?)
+		return L""; 
+	    } else {
+		// File finished without a newline, return what we've got.
+		return strtowc(res);
+	    }
+	}
+	if (res==NULL) {
+	    // FIXME: We're relying on \n or \r\n line endings. How much
+	    // can we rely on this?
+	    // C defines \n to be the native newline when reading
+	    // or writing files in text mode so maybe we're okay...
+	    if (strlen(buf)<(size-1) || buf[LINE_CHUNK-2]=='\n') {
+		return strtowc(buf); // Success in one chunk
+	    }
+	    // Begin allocation for accumulator and carry on as normal.
+	    size += LINE_CHUNK-1;
+	    res = (char*)GC_MALLOC_ATOMIC(size*sizeof(char)+1);
+	    strcpy(res,buf);
+	} 
+	else {
+	    strcat(res,buf);
+	    if (strlen(res)<(size-1) || buf[LINE_CHUNK-2]=='\n') { 
+                // Finished successfully
+		return strtowc(res); 
+	    } else {
+		size += LINE_CHUNK-1; // -1 to account for null termination of
+		                      // string read into buf
+		res = (char*)GC_REALLOC(res, size*sizeof(char)+1);
+	    }
+	}
+    } while (r!=NULL);
+    return L""; // Failed, although we shouldn't get here
 }
 
 wchar_t* getString(FILE* f)
 {
-// I know there's a better way. Can't be bothered.
-    char* buf=(char*)GC_MALLOC_ATOMIC(4096*sizeof(char)); 
+    unsigned size = LINE_CHUNK; // #define at top of file
+    // buffer to read into
+    char* buf=(char*)GC_MALLOC_ATOMIC(LINE_CHUNK*sizeof(char)+1); 
+    // accumulator for result; but only allocate it when it turns out to be
+    // needed (i.e., when one chunk isn't enough).
     int i=0;
-    while((buf[i++]=fgetc(f))!='\0') {}
-    buf[i]='\0';
-    return strtowc(buf);    
+    do {
+      
+      do {
+	int c = fgetc(f);
+	if (c == EOF) {
+	  buf[i] = '\0';
+	  return strtowc(buf);
+	} 
+	buf[i] = (unsigned char)c;
+	if (buf[i] == '\0') {
+	  return strtowc(buf);
+	}
+	i++;
+      } while (i%LINE_CHUNK != 0);
+      size += LINE_CHUNK;
+      buf = (char*)GC_REALLOC(buf, size*sizeof(char)+1);
+
+    } while (buf[i] != EOF);
+    return L""; // Failed, although we shouldn't get here
 }
 
 void putLine(FILE* f, wchar_t* c)
@@ -532,7 +595,7 @@
 	}
     }
     outblock[y]='\0';
-    KayaSetInt(outlen,y-1);
+    KayaSetInt(outlen,y);
     return outblock;
 }
 
--- stdlib/regex_glue.cc	2006-06-27 10:29:33.000000000 +0100
+++ /home/cim/kaya/stdlib/regex_glue.cc	2007-01-29 18:39:38.000000000 +0000
@@ -3,12 +3,13 @@
 #include "regex_glue.h"
 #include "Heap.h"
 #include "VM.h"
+#include "KayaAPI.h"
 
 void* re_compile(wchar_t* pattern, kint flagcode)
 {
     const char* error;
     int erroffset;
-    int regexflags = 0;
+    int regexflags = PCRE_UTF8;
     if (flagcode & 1) { regexflags = regexflags | PCRE_CASELESS; }
     if (flagcode & 2) { regexflags = regexflags | PCRE_EXTENDED; }
     if (flagcode & 4) { regexflags = regexflags | PCRE_MULTILINE; }
@@ -28,28 +29,40 @@
     int len = strlen(str);
 
 //    cout << rc << endl;
-
+    //cout << str << endl;
     if (rc>=0) {
 	m->matched = true;
 	m->matches = new Array();
 
-	m->before = (wchar_t*)GC_MALLOC((ovector[0]+1)*sizeof(wchar_t));
+	char* beforetmp = (char*)GC_MALLOC_ATOMIC((ovector[0]+1)*sizeof(char));
+	strncpy(beforetmp,str,ovector[0]);
+	beforetmp[ovector[0]] = '\0';
+	m->before = strtowc(beforetmp);
+
+	/*	m->before = (wchar_t*)GC_MALLOC_ATOMIC((ovector[0]+1)*sizeof(wchar_t));
 	wcsncpy(m->before, strtowc(str),ovector[0]);
 	m->before[ovector[0]]='\0';
+	cout << ovector[0] << endl; */
 
 	int afterlen = len-ovector[1];
-	m->after = (wchar_t*)GC_MALLOC((afterlen+1)*sizeof(wchar_t));
+	char* aftertmp = (char*)GC_MALLOC_ATOMIC((afterlen+1)*sizeof(char));
+	strncpy(aftertmp,str+ovector[1],afterlen);
+	aftertmp[afterlen] = '\0';
+	m->after = strtowc(aftertmp);
+
+	/*	m->after = (wchar_t*)GC_MALLOC_ATOMIC((afterlen+1)*sizeof(wchar_t));
 	wcsncpy(m->after, strtowc(str+ovector[1]),afterlen);
-	m->after[afterlen]='\0';
+	m->after[afterlen]='\0'; */
 
 	for(int i=0;i<rc;i++) {
 //	    cout << ovector[i*2] << "-" << ovector[i*2+1] << endl;
 	    const char* sub;
 	    pcre_get_substring(str, ovector, rc, i, &sub);
-	    char* val = (char*)GC_MALLOC((strlen(sub)+1)*sizeof(char));
-	    strcpy(val,sub);
-	    // this should really use the API!
-	    m->matches->push_back(new Value(new String(strtowc(val)),KVT_STRING));
+	    //	    char* val = (char*)GC_MALLOC_ATOMIC((strlen(sub)+1)*sizeof(char));
+	    //	    strcpy(val,sub);
+	    // this now uses the API!
+	    m->matches->push_back(KayaString(KSTRING(sub)));
+	    //new Value(new String(strtowc(sub)),KVT_STRING));
 	}
     }
     else

Reply via email to