<pre style='margin:0'>
Joshua Root (jmroot) pushed a commit to branch master
in repository macports-base.

</pre>
<p><a href="https://github.com/macports/macports-base/commit/4eb0095fb006ff5fb9d1a6a471c2a022f73a1aa1">https://github.com/macports/macports-base/commit/4eb0095fb006ff5fb9d1a6a471c2a022f73a1aa1</a></p>
<pre style="white-space: pre; background: #F8F8F8">The following commit(s) were added to refs/heads/master by this push:
<span style='display:block; white-space:pre;color:#404040;'>     new 4eb0095  Fix a crash due to an out-of-bounds array access
</span>4eb0095 is described below

<span style='display:block; white-space:pre;color:#808000;'>commit 4eb0095fb006ff5fb9d1a6a471c2a022f73a1aa1
</span>Author: Saagar Jha <saagar@saagarjha.com>
AuthorDate: Thu Feb 14 00:01:02 2019 -0800

<span style='display:block; white-space:pre;color:#404040;'>    Fix a crash due to an out-of-bounds array access
</span><span style='display:block; white-space:pre;color:#404040;'>    
</span><span style='display:block; white-space:pre;color:#404040;'>    entry_search had a "type confusion" bug where it would perform array
</span><span style='display:block; white-space:pre;color:#404040;'>    accesses that bypassed bounds checks if given arguments that looked like
</span><span style='display:block; white-space:pre;color:#404040;'>    strategies. I've rewritten most of the argument parsing loop in a way
</span><span style='display:block; white-space:pre;color:#404040;'>    that should eliminate this issue, while being shorter and more
</span><span style='display:block; white-space:pre;color:#404040;'>    straightforward (with less duplicated code), only requiring one pass
</span><span style='display:block; white-space:pre;color:#404040;'>    through the arguments. The downside is that we allocate a bit more
</span><span style='display:block; white-space:pre;color:#404040;'>    memory and have a couple of gotos to handle errors.
</span>---
 src/cregistry/entry.c           |   4 +-
 src/cregistry/entry.h           |   4 +-
 src/registry2.0/entry.c         | 170 +++++++++++++++++-----------------------
 src/registry2.0/tests/entry.tcl |   3 +
 4 files changed, 80 insertions(+), 101 deletions(-)

<span style='display:block; white-space:pre;color:#808080;'>diff --git a/src/cregistry/entry.c b/src/cregistry/entry.c
</span><span style='display:block; white-space:pre;color:#808080;'>index 74898c2..073e5ef 100644
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>--- a/src/cregistry/entry.c
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>+++ b/src/cregistry/entry.c
</span><span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -397,8 +397,8 @@ static int reg_all_entries(reg_registry* reg, char* query, int query_len,
</span>  * @param [out] errPtr   on error, a description of the error that occurred
  * @return               the number of entries if success; false if failure
  */
<span style='display:block; white-space:pre;background:#ffe0e0;'>-int reg_entry_search(reg_registry* reg, char** keys, char** vals, int key_count,
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-        int *strategies, reg_entry*** entries, reg_error* errPtr) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+int reg_entry_search(reg_registry* reg, const char** keys, const char** vals,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        int key_count, int *strategies, reg_entry*** entries, reg_error* errPtr) {
</span>     int i;
     char* kwd = " WHERE ";
     char* query;
<span style='display:block; white-space:pre;color:#808080;'>diff --git a/src/cregistry/entry.h b/src/cregistry/entry.h
</span><span style='display:block; white-space:pre;color:#808080;'>index 756a774..0c37aba 100644
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>--- a/src/cregistry/entry.h
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>+++ b/src/cregistry/entry.h
</span><span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -52,8 +52,8 @@ int reg_entry_delete(reg_entry* entry, reg_error* errPtr);
</span> 
 void reg_entry_free(reg_entry* entry);
 
<span style='display:block; white-space:pre;background:#ffe0e0;'>-int reg_entry_search(reg_registry* reg, char** keys, char** vals, int key_count,
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-        int* strategies, reg_entry*** entries, reg_error* errPtr);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+int reg_entry_search(reg_registry* reg, const char** keys, const char** vals,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        int key_count, int* strategies, reg_entry*** entries, reg_error* errPtr);
</span> 
 int reg_entry_imaged(reg_registry* reg, const char* name, const char* version,
         const char* revision, const char* variants, reg_entry*** entries,
<span style='display:block; white-space:pre;color:#808080;'>diff --git a/src/registry2.0/entry.c b/src/registry2.0/entry.c
</span><span style='display:block; white-space:pre;color:#808080;'>index abb6298..987b065 100644
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>--- a/src/registry2.0/entry.c
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>+++ b/src/registry2.0/entry.c
</span><span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -248,116 +248,92 @@ static strategy_type strategies[] = {
</span>  * Can be given an option of -exact, -glob, -regexp or -null to specify the
  * matching strategy; defaults to exact.
  */
<span style='display:block; white-space:pre;background:#ffe0e0;'>-static int entry_search(Tcl_Interp* interp, int objc, Tcl_Obj* CONST objv[]) {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-    int i, j;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-    reg_registry* reg = registry_for(interp, reg_attached);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-    if (reg == NULL) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+static int entry_search(Tcl_Interp* interp, int objc, Tcl_Obj* CONST *objv) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    reg_registry *reg = registry_for(interp, reg_attached);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    if (!reg) {
</span>         return TCL_ERROR;
<span style='display:block; white-space:pre;background:#ffe0e0;'>-    } else {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-        char** keys;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-        char** vals;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-        int* strats;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-        int key_count = 0;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-        reg_entry** entries;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-        reg_error error;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-        int entry_count;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-        for (i = 2; i < objc;) {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-            int index, strat_index, val_length;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-            if (Tcl_GetIndexFromObj(interp, objv[i], entry_props, "search key",
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-                        0, &index) != TCL_OK) {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-                return TCL_ERROR;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-            }
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-            /* we ate the key value */
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-            i++;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-            /* check whether there's a strategy */
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-            if (Tcl_GetString(objv[i])[0] == '-'
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-                    && Tcl_GetIndexFromObjStruct(interp, objv[i], strategies,
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-                        sizeof(strategy_type), "option", 0, &strat_index)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-                    != TCL_ERROR) {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-                /* this key has a strategy specified, eat the strategy parameter */
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-                i++;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-                if (strategies[strat_index].strategy != reg_strategy_null) {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-                    /* this key must also have a value */
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-                    if (Tcl_GetStringFromObj(objv[i], &val_length) == NULL) {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-                        Tcl_WrongNumArgs(interp, 2, objv,
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-                                "search ?key ?options? value ...?");
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-                        return TCL_ERROR;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-                    }
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-                    i++;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-                }
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-            } else {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-                /* this key must also have a value */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    const char **keys = malloc(objc * sizeof(char *));
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    const char **vals = malloc(objc * sizeof(char *));
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    int *strats = malloc(objc * sizeof(int));
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    if (!keys || !vals || !strats) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        goto cleanup_error;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    int key_count = 0;
</span> 
<span style='display:block; white-space:pre;background:#ffe0e0;'>-                if (Tcl_GetStringFromObj(objv[i], &val_length) == NULL) {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-                    Tcl_WrongNumArgs(interp, 2, objv,
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-                            "search ?key ?options? value ...?");
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-                    return TCL_ERROR;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-                }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    /* Skip the "registry::entry" "search" bit */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    objv += 2;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    objc -= 2;
</span> 
<span style='display:block; white-space:pre;background:#ffe0e0;'>-                i++;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-            }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    for (int i = 0; i < objc; ++key_count /* i in incremented in the loop */) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        int key_index, strategy_index;
</span> 
<span style='display:block; white-space:pre;background:#ffe0e0;'>-            key_count++;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        /* Grab the key */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        if (Tcl_GetIndexFromObj(interp, objv[i], entry_props, "search key",
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            0, &key_index) != TCL_OK) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            goto cleanup_error;
</span>         }
<span style='display:block; white-space:pre;background:#ffe0e0;'>-
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-        keys = malloc(key_count * sizeof(char*));
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-        vals = malloc(key_count * sizeof(char*));
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-        strats = malloc(key_count * sizeof(int));
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-        if (!keys || !vals || !strats) {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-            return TCL_ERROR;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        keys[key_count] = entry_props[key_index];
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        if (objc <= ++i) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            goto wrong_num_args; /* We're missing a strategy or value */
</span>         }
<span style='display:block; white-space:pre;background:#ffe0e0;'>-        for (i = 2, j = 0; i < objc && j < key_count; j++) {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-            int strat_index;
</span> 
<span style='display:block; white-space:pre;background:#ffe0e0;'>-            keys[j] = Tcl_GetString(objv[i++]);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-            /* try to get the strategy */
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-            if (Tcl_GetString(objv[i])[0] == '-'
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-                    && Tcl_GetIndexFromObjStruct(interp, objv[i], strategies,
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-                        sizeof(strategy_type), "option", 0, &strat_index)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-                    != TCL_ERROR) {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-                /* this key has a strategy specified */
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-                i++;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-                strats[j] = strategies[strat_index].strategy;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-            } else {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-                /* use default strategy */
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-                strats[j] = reg_strategy_exact;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        /* Set the default strategy, in case we don't find one */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        strats[key_count] = reg_strategy_exact;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        /* Try to grab the strategy */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        if (Tcl_GetIndexFromObjStruct(interp, objv[i], strategies,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                sizeof(strategy_type), "option", 0, &strategy_index) !=
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                TCL_ERROR) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            strats[key_count] = strategies[strategy_index].strategy;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            if (objc <= ++i && strats[key_count] != reg_strategy_null) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                goto wrong_num_args;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            } else if (strats[key_count] == reg_strategy_null) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                /* This doesn't take a value, so start from the top */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                continue;
</span>             }
<span style='display:block; white-space:pre;background:#e0ffe0;'>+        }
</span> 
<span style='display:block; white-space:pre;background:#ffe0e0;'>-            if (strats[j] != reg_strategy_null) {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-                vals[j] = Tcl_GetString(objv[i++]);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-            } else {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-                vals[j] = NULL;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-            }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        /* Grab the value */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        if (!(vals[key_count] = Tcl_GetString(objv[i++]))) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            goto wrong_num_args; /* We're missing a value */
</span>         }
<span style='display:block; white-space:pre;background:#ffe0e0;'>-        entry_count = reg_entry_search(reg, keys, vals, key_count,
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-                strats, &entries, &error);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-        free(keys);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-        free(vals);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-        free(strats);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-        if (entry_count >= 0) {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-            int retval;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-            Tcl_Obj* resultObj;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-            Tcl_Obj** objs;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-            if (list_entry_to_obj(interp, &objs, entries, entry_count, &error)){
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-                resultObj = Tcl_NewListObj(entry_count, objs);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-                Tcl_SetObjResult(interp, resultObj);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-                free(objs);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-                retval = TCL_OK;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-            } else {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-                retval = registry_failed(interp, &error);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-            }
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-            free(entries);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-            return retval;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    reg_entry **entries;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    reg_error error;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    int entry_count;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    entry_count = reg_entry_search(reg, keys, vals, key_count, strats, &entries,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        &error);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    free(keys);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    free(vals);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    free(strats);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    if (entry_count >= 0) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        int retval;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        Tcl_Obj* resultObj;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        Tcl_Obj** objs;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        if (list_entry_to_obj(interp, &objs, entries, entry_count, &error)){
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            resultObj = Tcl_NewListObj(entry_count, objs);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            Tcl_SetObjResult(interp, resultObj);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            free(objs);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            retval = TCL_OK;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        } else {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            retval = registry_failed(interp, &error);
</span>         }
<span style='display:block; white-space:pre;background:#e0ffe0;'>+        free(entries);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        return retval;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    } else {
</span>         return registry_failed(interp, &error);
     }
<span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+wrong_num_args:
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    Tcl_WrongNumArgs(interp, 2, objv,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            "search ?key ?options? value ...?");
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+cleanup_error:
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    free(keys);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    free(vals);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    free(strats);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    return TCL_ERROR;
</span> }
 
 /*
<span style='display:block; white-space:pre;color:#808080;'>diff --git a/src/registry2.0/tests/entry.tcl b/src/registry2.0/tests/entry.tcl
</span><span style='display:block; white-space:pre;color:#808080;'>index b4505bd..9c487f0 100644
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>--- a/src/registry2.0/tests/entry.tcl
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>+++ b/src/registry2.0/tests/entry.tcl
</span><span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -74,6 +74,9 @@ proc main {pextlibname} {
</span>         test_set {[registry::entry search name -glob vi*]} {$vim1 $vim2 $vim3}
         test_set {[registry::entry search name -regexp {zlib|pcre}]} \
             {$zlib $pcre}
<span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        # test that passing in confusing arguments doesn't crash
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        test {[catch {registry::entry search name vim1 --}] == 1}
</span>     }
 
     # try mapping files and checking their owners
</pre><pre style='margin:0'>

</pre>