Repository: lucy-clownfish
Updated Branches:
  refs/heads/master dba8fd508 -> 9f31a790e


Disallow invalid code points in CB_Cat_Char


Project: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/commit/ca3809d7
Tree: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/tree/ca3809d7
Diff: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/diff/ca3809d7

Branch: refs/heads/master
Commit: ca3809d7fb99d8905c83dcbf90221dca2c69bc41
Parents: dba8fd5
Author: Nick Wellnhofer <wellnho...@aevum.de>
Authored: Tue Aug 2 18:06:02 2016 +0200
Committer: Nick Wellnhofer <wellnho...@aevum.de>
Committed: Tue Aug 2 18:06:02 2016 +0200

----------------------------------------------------------------------
 runtime/core/Clownfish/CharBuf.c          |  6 +++
 runtime/test/Clownfish/Test/TestCharBuf.c | 67 +++++++++++++++++++++++++-
 2 files changed, 72 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/ca3809d7/runtime/core/Clownfish/CharBuf.c
----------------------------------------------------------------------
diff --git a/runtime/core/Clownfish/CharBuf.c b/runtime/core/Clownfish/CharBuf.c
index 8661c7b..2dbae91 100644
--- a/runtime/core/Clownfish/CharBuf.c
+++ b/runtime/core/Clownfish/CharBuf.c
@@ -280,6 +280,12 @@ CB_Yield_String_IMP(CharBuf *self) {
 
 void
 CB_Cat_Char_IMP(CharBuf *self, int32_t code_point) {
+    if (code_point < 0
+        || (code_point >= 0xD800 && code_point < 0xE000)
+        || code_point >= 0x110000
+       ) {
+        THROW(ERR, "Invalid code point: 0x%x32", (uint32_t)code_point);
+    }
     const size_t MAX_UTF8_BYTES = 4;
     size_t old_size = self->size;
     SI_add_grow_and_oversize(self, old_size, MAX_UTF8_BYTES);

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/ca3809d7/runtime/test/Clownfish/Test/TestCharBuf.c
----------------------------------------------------------------------
diff --git a/runtime/test/Clownfish/Test/TestCharBuf.c 
b/runtime/test/Clownfish/Test/TestCharBuf.c
index 4329987..0782ce2 100644
--- a/runtime/test/Clownfish/Test/TestCharBuf.c
+++ b/runtime/test/Clownfish/Test/TestCharBuf.c
@@ -32,6 +32,7 @@
 #include "Clownfish/Test.h"
 #include "Clownfish/TestHarness/TestBatchRunner.h"
 #include "Clownfish/TestHarness/TestUtils.h"
+#include "Clownfish/Util/StringHelper.h"
 #include "Clownfish/Class.h"
 
 static char smiley[] = { (char)0xE2, (char)0x98, (char)0xBA, 0 };
@@ -102,6 +103,68 @@ test_Cat(TestBatchRunner *runner) {
 }
 
 static void
+test_roundtrip(TestBatchRunner *runner) {
+    CharBuf *cb = CB_new(0);
+    int32_t code_point;
+
+    for (code_point = 0; code_point <= 0x10FFFF; code_point++) {
+        if (code_point >= 0xD800 && code_point <= 0xDFFF) { continue; }
+
+        CB_Cat_Char(cb, code_point);
+        String *str = CB_Yield_String(cb);
+        const char *start = Str_Get_Ptr8(str);
+        size_t size = Str_Get_Size(str);
+
+        // Verify that utf8_valid agrees.
+        if (!StrHelp_utf8_valid(start, size)) {
+            break;
+        }
+
+        // Verify round trip of encode/decode.
+        if (Str_Code_Point_At(str, 0) != code_point) {
+            break;
+        }
+
+        DECREF(str);
+    }
+    if (code_point == 0x110000) {
+        PASS(runner, "Successfully round tripped 0 - 0x10FFFF");
+    }
+    else {
+        FAIL(runner, "Failed round trip at 0x%04X", (unsigned)code_point);
+    }
+}
+
+typedef struct {
+    CharBuf *cb;
+    int32_t  code_point;
+} CatCharContext;
+
+static void
+S_cat_invalid_char(void *vcontext) {
+    CatCharContext *context = (CatCharContext*)vcontext;
+    CB_Cat_Char(context->cb, context->code_point);
+}
+
+static void
+test_invalid_chars(TestBatchRunner *runner) {
+    static const int32_t cps[] = { -1, 0xD800, 0xDFFF, 0x110000 };
+    size_t num_cps = sizeof(cps) / sizeof(cps[0]);
+    CatCharContext context;
+    context.cb = CB_new(0);
+
+    for (size_t i = 0; i < num_cps; i++) {
+        context.code_point = cps[i];
+        Err *error = Err_trap(S_cat_invalid_char, &context);
+        TEST_TRUE(runner, error != NULL, "Cat_Char with invalid code point %d",
+                  (int)cps[i]);
+        DECREF(error);
+    }
+
+    DECREF(context.cb);
+}
+
+static void
 test_Clone(TestBatchRunner *runner) {
     String  *wanted    = S_get_str("foo");
     CharBuf *wanted_cb = S_get_cb("foo");
@@ -368,7 +431,7 @@ test_Get_Size(TestBatchRunner *runner) {
 
 void
 TestCB_Run_IMP(TestCharBuf *self, TestBatchRunner *runner) {
-    TestBatchRunner_Plan(runner, (TestBatch*)self, 41);
+    TestBatchRunner_Plan(runner, (TestBatch*)self, 46);
     test_vcatf_percent(runner);
     test_vcatf_s(runner);
     test_vcatf_s_invalid_utf8(runner);
@@ -386,6 +449,8 @@ TestCB_Run_IMP(TestCharBuf *self, TestBatchRunner *runner) {
     test_vcatf_x32(runner);
     test_vcatf_invalid(runner);
     test_Cat(runner);
+    test_roundtrip(runner);
+    test_invalid_chars(runner);
     test_Clone(runner);
     test_Clear(runner);
     test_Grow(runner);

Reply via email to