about summary refs log tree commit
diff options
context:
space:
mode:
authorEric Wong <normalperson@yhbt.net>2011-06-02 20:21:34 +0000
committerEric Wong <normalperson@yhbt.net>2011-06-02 20:21:34 +0000
commit77f0be59a45d9ed6dd5f87c8cff90da90a17e421 (patch)
tree13eaf869adf1e3349e7984007f13e15e13095a82
parent30b00d8bc02f2ae0fe871eb50fa342c53714751d (diff)
downloadrpatricia-77f0be59a45d9ed6dd5f87c8cff90da90a17e421.tar.gz
prefix_toa2x requires proper length for IPv6
We have the INET6_ADDRSTRLEN constant to help us determine
the proper length.
-rw-r--r--ext/rpatricia/patricia.c45
-rw-r--r--ext/rpatricia/patricia.h1
-rw-r--r--ext/rpatricia/rpatricia.c24
3 files changed, 36 insertions, 34 deletions
diff --git a/ext/rpatricia/patricia.c b/ext/rpatricia/patricia.c
index fcbb110..44cc01c 100644
--- a/ext/rpatricia/patricia.c
+++ b/ext/rpatricia/patricia.c
@@ -70,39 +70,32 @@ comp_with_mask (void *addr, void *dest, u_int mask)
 /*
  * convert prefix information to ascii string with length
  * thread safe and re-entrant implementation
+ *
+ * buff must be at least PATRICIA_MAXSTRLEN bytes large if with_len is true
+ * buff must be at least INET6_ADDRSTRLEN bytes large if with_len is false
  */
 char *
 prefix_toa2x (prefix_t *prefix, char *buff, int with_len)
 {
-    if (prefix == NULL)
-        return ("(Null)");
-    assert (prefix->ref_count >= 0);
+    assert(prefix && "NULL prefix not allowed");
+    assert(prefix->ref_count >= 0);
     assert(buff != NULL && "buffer must be specified");
 
-    if (prefix->family == AF_INET) {
-        u_char *a;
-        assert (prefix->bitlen <= 32);
-        a = prefix_touchar (prefix);
-        if (with_len) {
-            sprintf (buff, "%d.%d.%d.%d/%d", a[0], a[1], a[2], a[3],
-                     prefix->bitlen);
-        }
-        else {
-            sprintf (buff, "%d.%d.%d.%d", a[0], a[1], a[2], a[3]);
-        }
-        return (buff);
-    }
-    else if (prefix->family == AF_INET6) {
-        char *r;
-        r = (char *) inet_ntop (AF_INET6, &prefix->add.sin6, buff, 48 /* a guess value */ );
-        if (r && with_len) {
-            assert (prefix->bitlen <= 128);
-            sprintf (buff + strlen (buff), "/%d", prefix->bitlen);
-        }
-        return (buff);
+    switch (prefix->family) {
+    case AF_INET:
+        assert(prefix->bitlen <= 32 && "bitlen > 32 for AF_INET");
+        break;
+    case AF_INET6:
+        assert(prefix->bitlen <= 128 && "bitlen > 128 for AF_INET6");
+        break;
+    default:
+        assert(0 && "unknown address family (memory corruption?)");
     }
-    else
-        return (NULL);
+    buff = inet_ntop(prefix->family, &prefix->add.sin6, buff, INET6_ADDRSTRLEN);
+    assert(buff && "corrupt address");
+    if (with_len)
+        sprintf(buff + strlen(buff), "/%u", prefix->bitlen);
+    return (buff);
 }
 
 /* prefix_toa2
diff --git a/ext/rpatricia/patricia.h b/ext/rpatricia/patricia.h
index d4bb7ab..f4abffd 100644
--- a/ext/rpatricia/patricia.h
+++ b/ext/rpatricia/patricia.h
@@ -91,6 +91,7 @@ ascii2prefix (char *string);
 /* } */
 
 #define PATRICIA_MAXBITS 128
+#define PATRICIA_MAXSTRLEN (INET6_ADDRSTRLEN + sizeof("/128") - 1)
 #define PATRICIA_NBIT(x)        (0x80 >> ((x) & 0x7f))
 #define PATRICIA_NBYTE(x)       ((x) >> 3)
 
diff --git a/ext/rpatricia/rpatricia.c b/ext/rpatricia/rpatricia.c
index 98b9b35..17534c6 100644
--- a/ext/rpatricia/rpatricia.c
+++ b/ext/rpatricia/rpatricia.c
@@ -177,7 +177,7 @@ p_print_nodes (int argc, VALUE *argv, VALUE self)
 {
   ID id_printf = rb_intern("printf");
   VALUE fmt = rb_str_new2("node: %s\n");
-  VALUE buf = rb_str_buf_new(128);
+  VALUE buf = rb_str_new(0, 0);
   char *cbuf;
   patricia_tree_t *tree;
   patricia_node_t *node;
@@ -190,7 +190,7 @@ p_print_nodes (int argc, VALUE *argv, VALUE self)
 
   if (tree->head) {
     PATRICIA_WALK(tree->head, node) {
-      rb_str_resize(buf, 128);
+      rb_str_resize(buf, PATRICIA_MAXSTRLEN);
       cbuf = RSTRING_PTR(buf);
       prefix_toa2x(node->prefix, cbuf, 1);
       rb_str_set_len(buf, strlen(cbuf));
@@ -219,21 +219,29 @@ p_data (VALUE self)
 static VALUE
 p_network (VALUE self)
 {
-  char buff[32];
   patricia_node_t *node;
+  VALUE str = rb_str_new(0, PATRICIA_MAXSTRLEN);
+  char *cstr = RSTRING_PTR(str);
+
   Data_Get_Struct(self, patricia_node_t, node);
-  prefix_toa2x (node->prefix, buff, 0);
-  return rb_str_new2(buff);
+  prefix_toa2x(node->prefix, cstr, 0);
+  rb_str_set_len(str, strlen(cstr));
+
+  return str;
 }
 
 static VALUE
 p_prefix (VALUE self)
 {
-  char buff[32];
   patricia_node_t *node;
+  VALUE str = rb_str_new(0, INET6_ADDRSTRLEN);
+  char *cstr = RSTRING_PTR(str);
+
   Data_Get_Struct(self, patricia_node_t, node);
-  prefix_toa2 (node->prefix, buff);
-  return rb_str_new2(buff);
+  prefix_toa2(node->prefix, cstr);
+  rb_str_set_len(str, strlen(cstr));
+
+  return str;
 }
 
 static VALUE