[gjs/gnome-40] byteArray: Fix crash with 0-length GLib.Bytes



commit 1a71d5b0dd53c1c951751fdd71dad931ae834ffb
Author: Philip Chimento <philip chimento gmail com>
Date:   Sun May 23 15:33:43 2021 -0700

    byteArray: Fix crash with 0-length GLib.Bytes
    
    ByteArray.fromGBytes() would crash if the GLib.Bytes had zero length.
    Anticipate this case and just create an empty Uint8Array.

 gjs/byteArray.cpp                   | 28 ++++++++++++++++++----------
 installed-tests/js/testByteArray.js |  5 +++++
 2 files changed, 23 insertions(+), 10 deletions(-)
---
diff --git a/gjs/byteArray.cpp b/gjs/byteArray.cpp
index 4fe361d1..e8e294ff 100644
--- a/gjs/byteArray.cpp
+++ b/gjs/byteArray.cpp
@@ -214,6 +214,13 @@ to_gbytes_func(JSContext *context,
     return true;
 }
 
+GJS_JSAPI_RETURN_CONVENTION
+static bool define_legacy_tostring(JSContext* cx, JS::HandleObject array) {
+    const GjsAtoms& atoms = GjsContextPrivate::atoms(cx);
+    return JS_DefineFunctionById(cx, array, atoms.to_string(),
+                                 instance_to_string_func, 1, 0);
+}
+
 /* fromString() function implementation */
 GJS_JSAPI_RETURN_CONVENTION
 static bool
@@ -297,10 +304,7 @@ from_string_func(JSContext *context,
     if (!array_buffer)
         return false;
     obj = JS_NewUint8ArrayWithBuffer(context, array_buffer, 0, -1);
-
-    const GjsAtoms& atoms = GjsContextPrivate::atoms(context);
-    if (!JS_DefineFunctionById(context, obj, atoms.to_string(),
-                               instance_to_string_func, 1, 0))
+    if (!obj || !define_legacy_tostring(context, obj))
         return false;
 
     argv.rval().setObject(*obj);
@@ -330,6 +334,15 @@ from_gbytes_func(JSContext *context,
 
     size_t len;
     const void* data = g_bytes_get_data(gbytes, &len);
+    if (len == 0) {
+        JS::RootedObject empty_array(context, JS_NewUint8Array(context, 0));
+        if (!empty_array || !define_legacy_tostring(context, empty_array))
+            return false;
+
+        argv.rval().setObject(*empty_array);
+        return true;
+    }
+
     JS::RootedObject array_buffer(
         context,
         JS::NewExternalArrayBuffer(
@@ -342,12 +355,7 @@ from_gbytes_func(JSContext *context,
 
     JS::RootedObject obj(
         context, JS_NewUint8ArrayWithBuffer(context, array_buffer, 0, -1));
-    if (!obj)
-        return false;
-
-    const GjsAtoms& atoms = GjsContextPrivate::atoms(context);
-    if (!JS_DefineFunctionById(context, obj, atoms.to_string(),
-                               instance_to_string_func, 1, 0))
+    if (!obj || !define_legacy_tostring(context, obj))
         return false;
 
     argv.rval().setObject(*obj);
diff --git a/installed-tests/js/testByteArray.js b/installed-tests/js/testByteArray.js
index 10fcdaa1..bcae4183 100644
--- a/installed-tests/js/testByteArray.js
+++ b/installed-tests/js/testByteArray.js
@@ -68,6 +68,11 @@ describe('Byte array', function () {
         expect(ByteArray.toGBytes(a).get_size()).toEqual(0);
     });
 
+    it('deals gracefully with a 0-length GLib.Bytes', function () {
+        const noBytes = ByteArray.toGBytes(new Uint8Array(0));
+        expect(ByteArray.fromGBytes(noBytes).length).toEqual(0);
+    });
+
     it('deals gracefully with a non Uint8Array', function () {
         const a = [97, 98, 99, 100, 0];
         expect(() => ByteArray.toString(a)).toThrow();


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]