[gjs: 6/11] js: Report out of memory on failed vector operations



commit 717e8a45cad0734d5f56e9214e115d830e8885ef
Author: Philip Chimento <philip chimento gmail com>
Date:   Mon Oct 15 21:00:47 2018 -0700

    js: Report out of memory on failed vector operations
    
    Instead of aborting immediately, use JS_ReportOutOfMemory() when a vector
    operation fails, i.e. the vector can't grow anymore. The result is likely
    going to be the same in the end, but this will allow us to do more
    sophisticated recovery from out-of-memory errors in the future.
    
    In some places we still have to keep the old behaviour because the
    functions doing the operations are themselves infallible. These we will
    fix in the next commit.

 gi/arg.cpp         | 36 ++++++++++++++++++++++++------------
 gi/object.cpp      | 24 ++++++++++++++++--------
 gjs/importer.cpp   | 12 ++++++++----
 gjs/jsapi-util.cpp | 15 +++++++++------
 gjs/module.cpp     |  6 ++++--
 5 files changed, 61 insertions(+), 32 deletions(-)
---
diff --git a/gi/arg.cpp b/gi/arg.cpp
index 4b4cdf12..911730bc 100644
--- a/gi/arg.cpp
+++ b/gi/arg.cpp
@@ -599,8 +599,10 @@ gjs_array_from_strv(JSContext             *context,
      * the case.
      */
     for (i = 0; strv != NULL && strv[i] != NULL; i++) {
-        if (!elems.growBy(1))
-            g_error("Unable to grow vector");
+        if (!elems.growBy(1)) {
+            JS_ReportOutOfMemory(context);
+            return false;
+        }
 
         if (!gjs_string_from_utf8(context, strv[i], elems[i]))
             return false;
@@ -991,8 +993,10 @@ gjs_array_from_flat_gvalue_array(JSContext             *context,
 
     unsigned int i;
     JS::AutoValueVector elems(context);
-    if (!elems.resize(length))
-        g_error("Unable to resize vector");
+    if (!elems.resize(length)) {
+        JS_ReportOutOfMemory(context);
+        return false;
+    }
 
     bool result = true;
 
@@ -2259,8 +2263,10 @@ gjs_array_from_g_list (JSContext             *context,
     if (list_tag == GI_TYPE_TAG_GLIST) {
         for ( ; list != NULL; list = list->next) {
             arg.v_pointer = list->data;
-            if (!elems.growBy(1))
-                g_error("Unable to grow vector");
+            if (!elems.growBy(1)) {
+                JS_ReportOutOfMemory(context);
+                return false;
+            }
 
             if (!gjs_value_from_g_argument(context, elems[i], param_info, &arg,
                                            true))
@@ -2270,8 +2276,10 @@ gjs_array_from_g_list (JSContext             *context,
     } else {
         for ( ; slist != NULL; slist = slist->next) {
             arg.v_pointer = slist->data;
-            if (!elems.growBy(1))
-                g_error("Unable to grow vector");
+            if (!elems.growBy(1)) {
+                JS_ReportOutOfMemory(context);
+                return false;
+            }
 
             if (!gjs_value_from_g_argument(context, elems[i], param_info, &arg,
                                            true))
@@ -2329,8 +2337,10 @@ gjs_array_from_carray_internal (JSContext             *context,
     }
 
     JS::AutoValueVector elems(context);
-    if (!elems.resize(length))
-        g_error("Unable to resize vector");
+    if (!elems.resize(length)) {
+        JS_ReportOutOfMemory(context);
+        return false;
+    }
 
 #define ITERATE(type) \
     for (i = 0; i < length; i++) { \
@@ -2547,8 +2557,10 @@ gjs_array_from_zero_terminated_c_array (JSContext             *context,
         g##type *array = (g##type *) c_array; \
         for (i = 0; array[i]; i++) { \
             arg.v_##type = array[i]; \
-            if (!elems.growBy(1))                                       \
-                g_error("Unable to grow vector");                       \
+            if (!elems.growBy(1)) {                                     \
+                JS_ReportOutOfMemory(context);                          \
+                return false;                                           \
+            }                                                           \
             if (!gjs_value_from_g_argument(context, elems[i],           \
                                            param_info, &arg, true))     \
                 return false; \
diff --git a/gi/object.cpp b/gi/object.cpp
index 9d19672e..0edb003e 100644
--- a/gi/object.cpp
+++ b/gi/object.cpp
@@ -294,8 +294,10 @@ GParamSpec* ObjectPrototype::find_param_spec_from_id(JSContext* cx,
         return nullptr;
     }
 
-    if (!m_property_cache.add(entry, key, std::move(param_spec)))
-        g_error("Out of memory adding param spec to cache");
+    if (!m_property_cache.add(entry, key, std::move(param_spec))) {
+        JS_ReportOutOfMemory(cx);
+        return nullptr;
+    }
     return pspec; /* owned by property cache */
 }
 
@@ -441,8 +443,10 @@ GIFieldInfo* ObjectPrototype::find_field_info_from_id(JSContext* cx,
         return nullptr;
     }
 
-    if (!m_field_cache.add(entry, key, std::move(field)))
-        g_error("Out of memory adding field info to cache");
+    if (!m_field_cache.add(entry, key, std::move(field))) {
+        JS_ReportOutOfMemory(cx);
+        return nullptr;
+    }
     return entry->value().get();  /* owned by field cache */
 }
 
@@ -1009,7 +1013,8 @@ bool ObjectPrototype::new_enumerate_impl(JSContext* cx, JS::HandleObject obj,
             if (flags & GI_FUNCTION_IS_METHOD) {
                 const char* name = meth_info.name();
                 if (!properties.append(gjs_intern_string_to_id(cx, name))) {
-                    g_error("Unable to append to vector");
+                    JS_ReportOutOfMemory(cx);
+                    return false;
                 }
             }
         }
@@ -1023,7 +1028,8 @@ bool ObjectPrototype::new_enumerate_impl(JSContext* cx, JS::HandleObject obj,
             GjsAutoChar js_name = gjs_hyphen_to_underscore(prop_info.name());
 
             if (!properties.append(gjs_intern_string_to_id(cx, js_name))) {
-                g_error("Unable to append to vector");
+                JS_ReportOutOfMemory(cx);
+                return false;
             }
         }
     }
@@ -1040,7 +1046,8 @@ bool ObjectPrototype::new_enumerate_impl(JSContext* cx, JS::HandleObject obj,
             if (flags & GI_FUNCTION_IS_METHOD) {
                 const char* name = meth_info.name();
                 if (!properties.append(gjs_intern_string_to_id(cx, name))) {
-                    g_error("Unable to append to vector");
+                    JS_ReportOutOfMemory(cx);
+                    return false;
                 }
             }
         }
@@ -1054,7 +1061,8 @@ bool ObjectPrototype::new_enumerate_impl(JSContext* cx, JS::HandleObject obj,
             GjsAutoChar js_name = gjs_hyphen_to_underscore(prop_info.name());
 
             if (!properties.append(gjs_intern_string_to_id(cx, js_name))) {
-                g_error("Unable to append to vector");
+                JS_ReportOutOfMemory(cx);
+                return false;
             }
         }
     }
diff --git a/gjs/importer.cpp b/gjs/importer.cpp
index f056b849..58d9ec6e 100644
--- a/gjs/importer.cpp
+++ b/gjs/importer.cpp
@@ -707,14 +707,18 @@ static bool importer_new_enumerate(JSContext* context, JS::HandleObject object,
                 continue;
 
             if (g_file_info_get_file_type(info) == G_FILE_TYPE_DIRECTORY) {
-                if (!properties.append(gjs_intern_string_to_id(context, filename)))
-                    g_error("Unable to append to vector");
+                if (!properties.append(gjs_intern_string_to_id(context, filename))) {
+                    JS_ReportOutOfMemory(context);
+                    return false;
+                }
             } else if (g_str_has_suffix(filename, "." G_MODULE_SUFFIX) ||
                        g_str_has_suffix(filename, ".js")) {
                 GjsAutoChar filename_noext =
                     g_strndup(filename, strlen(filename) - 3);
-                if (!properties.append(gjs_intern_string_to_id(context, filename_noext)))
-                    g_error("Unable to append to vector");
+                if (!properties.append(gjs_intern_string_to_id(context, filename_noext))) {
+                    JS_ReportOutOfMemory(context);
+                    return false;
+                }
             }
         }
     }
diff --git a/gjs/jsapi-util.cpp b/gjs/jsapi-util.cpp
index 59ab67f4..8db9516b 100644
--- a/gjs/jsapi-util.cpp
+++ b/gjs/jsapi-util.cpp
@@ -304,15 +304,16 @@ gjs_build_string_array(JSContext   *context,
         array_length = g_strv_length(array_values);
 
     JS::AutoValueVector elems(context);
-    if (!elems.reserve(array_length))
-        g_error("Unable to reserve memory for vector");
+    if (!elems.reserve(array_length)) {
+        JS_ReportOutOfMemory(context);
+        return nullptr;
+    }
 
     for (i = 0; i < array_length; ++i) {
         JS::ConstUTF8CharsZ chars(array_values[i], strlen(array_values[i]));
         JS::RootedValue element(context,
             JS::StringValue(JS_NewStringCopyUTF8Z(context, chars)));
-        if (!elems.append(element))
-            g_error("Unable to append to vector");
+        elems.infallibleAppend(element);
     }
 
     return JS_NewArrayObject(context, elems);
@@ -821,8 +822,10 @@ gjs_eval_with_scope(JSContext             *context,
                                JS::SourceBufferHolder::NoOwnership);
 
     JS::AutoObjectVector scope_chain(context);
-    if (!scope_chain.append(eval_obj))
-        g_error("Unable to append to vector");
+    if (!scope_chain.append(eval_obj)) {
+        JS_ReportOutOfMemory(context);
+        return false;
+    }
 
     if (!JS::Evaluate(context, scope_chain, options, buf, retval))
         return false;
diff --git a/gjs/module.cpp b/gjs/module.cpp
index 7a50ece5..e2ab5709 100644
--- a/gjs/module.cpp
+++ b/gjs/module.cpp
@@ -101,8 +101,10 @@ class GjsModule {
                                    JS::SourceBufferHolder::NoOwnership);
 
         JS::AutoObjectVector scope_chain(cx);
-        if (!scope_chain.append(module))
-            g_error("Unable to append to vector");
+        if (!scope_chain.append(module)) {
+            JS_ReportOutOfMemory(cx);
+            return false;
+        }
 
         JS::RootedValue ignored_retval(cx);
         if (!JS::Evaluate(cx, scope_chain, options, buf, &ignored_retval))


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