Saluton!

This message contains a C implementation of a string buffer (see
below). It is an alpha version because I have no information about
the behavior of ALLOC_N and REALLOC_N in the case of a memory
allocation failure -  I didn't find any documentation on that topic.
Besides that it seems to be bullet-proof (I use it to to concatenate
chunks of all mails I download from my POP3 accounts - which is the
reason why I want to avoid vulnerabilities).

As every C programmer knows not checking the return value of 'malloc'
is a vulnerability to be exploited. In the case of the Rubyish
routines ALLOC_N and REALLOC_N two different behaviors are equally
likely:

 - return NULL buffer in the same way as plain C functions do

 - raise an exception

I did assume the latter but if the former is true that will mean the
code given below is vulnerable to exploits!

* Dominik Werder; 2003-06-13, 13:18 UTC:
> What is the fastest way to add many small Strings to a big buffer?

Follows my C version for that problem: 'new' set size of buffer,
append does append to it (if capacity is too slow it is automagically
increased), get gets whole buffer.

-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

#include <ruby.h>
#include <string.h>

VALUE cStorage;
char *m = NULL;
char *end = NULL;
int capacity = 0;

static VALUE resize(VALUE, VALUE);

static VALUE new(VALUE self, VALUE size) {
  resize(self, size);
  *m = '\0';
  end = m;
  return self;
}

static VALUE resize(VALUE self, VALUE size) {
  int chars;

  Check_Type(size, T_FIXNUM);
  chars = NUM2ULONG(size);

  if (!m) {
    m = ALLOC_N(char, chars + 1);
    capacity = chars;
  } else if (capacity < chars) {
    REALLOC_N(m, char, chars + 1);
    capacity = chars;
  }
  return self;
}

static VALUE append(VALUE self, VALUE text) {
  int len;
  char * str;

  Check_Type(text, T_STRING);
  str = STR2CSTR(text);
  len = strlen(str);

  if (end - m + len > capacity) resize(self, end - m + len);

  strcat(end, str);
  end += len;
  return self;
}

static VALUE get(VALUE self) {
  return rb_str_new2(m);
}

void Init_Storage() {
  cStorage = rb_define_module("Storage");
  rb_define_module_function(cStorage, "new", new, 1);
  rb_define_module_function(cStorage, "append", append, 1);
  rb_define_module_function(cStorage, "get", get, 0);
}

-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

Gis,

Josef 'Jupp' Schugt