Optional property query support.
authorPauli <paul.dale@oracle.com>
Thu, 16 May 2019 04:50:18 +0000 (14:50 +1000)
committerPauli <paul.dale@oracle.com>
Wed, 22 May 2019 00:45:39 +0000 (10:45 +1000)
Add the possibility of a property query clause to be optional by preceding
it with a question mark.

Reviewed-by: Richard Levitte <levitte@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/8943)

crypto/property/properties.ebnf
crypto/property/properties.xhtml [changed mode: 0644->0755]
crypto/property/property.c
crypto/property/property_lcl.h
crypto/property/property_parse.c
test/property_test.c

index 9a6857f751452dee43a0d7bf6798f5b74f0c8c31..0051c7e43095e4745878d18772a5a6302da106a3 100644 (file)
@@ -2,16 +2,17 @@
 
 Definition
       ::= PropertyName ( '=' Value )? ( ',' PropertyName ( '=' Value )? )*
-Query ::= ( '-'? PropertyName | PropertyName ( '=' | '!=' ) Value )
-          ( ',' ( '-'? PropertyName | PropertyName ( '=' | '!=' ) Value ) )*
+Query ::= PropertyQuery ( ',' PropertyQuery )*
+PropertyQuery ::= '-'? PropertyName
+        | '?' ( PropertyName (( '=' | '!=' ) Value)?)
 Value    ::= NumberLiteral
         | StringLiteral
 StringLiteral ::= QuotedString | UnquotedString
 QuotedString     ::= '"' [^"]* '"'
-       | "'" [^']* "'"
+        | "'" [^']* "'"
 UnquotedString ::= [^{space},]+
 NumberLiteral
      ::= '0' ( [0-7]* | 'x' [0-9A-Fa-f]+ )
-       | '-'? [1-9] [0-9]+
+        | '-'? [1-9] [0-9]+
 PropertyName
          ::= [A-Z] [A-Z0-9_]* ( '.' [A-Z] [A-Z0-9_]* )*
old mode 100644 (file)
new mode 100755 (executable)
index 3382722..766d885
@@ -2,7 +2,7 @@
 <html xmlns="http://www.w3.org/1999/xhtml">
    <head>
       <meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
-      <meta name="generator" content="Railroad Diagram Generator 1.56.1774" />
+      <meta name="generator" content="Railroad Diagram Generator 1.59.1797" />
       <style type="text/css">
     ::-moz-selection
     {
       display: block;
       padding: 10px;
       background: #FFF6D1;
-      width: 1000px;
+      width: 992px;
     }
     #divs div.grammar
     {
                <div><a href="#Definition" title="Definition">Definition</a></div>
                <div>         ::= <a href="#PropertyName" title="PropertyName">PropertyName</a> ( '=' <a href="#Value" title="Value">Value</a> )? ( ',' <a href="#PropertyName" title="PropertyName">PropertyName</a> ( '=' <a href="#Value" title="Value">Value</a> )? )*</div></xhtml:code></xhtml:div>
       </xhtml:p>
-      <xhtml:p xmlns:xhtml="http://www.w3.org/1999/xhtml">no references</xhtml:p><xhtml:br xmlns:xhtml="http://www.w3.org/1999/xhtml" /><xhtml:p xmlns:xhtml="http://www.w3.org/1999/xhtml" style="font-size: 14px; font-weight:bold"><xhtml:a name="Query">Query:</xhtml:a></xhtml:p><svg xmlns="http://www.w3.org/2000/svg" width="419" height="201">
+      <xhtml:p xmlns:xhtml="http://www.w3.org/1999/xhtml">no references</xhtml:p><xhtml:br xmlns:xhtml="http://www.w3.org/1999/xhtml" /><xhtml:p xmlns:xhtml="http://www.w3.org/1999/xhtml" style="font-size: 14px; font-weight:bold"><xhtml:a name="Query">Query:</xhtml:a></xhtml:p><svg xmlns="http://www.w3.org/2000/svg" width="211" height="81">
          <defs>
             <style type="text/css">
     @namespace "http://www.w3.org/2000/svg";
   </style>
          </defs>
          <polygon points="9 61 1 57 1 65"/>
-         <polygon points="17 61 9 57 9 65"/>
-         <rect x="91" y="79" width="26" height="32" rx="10"/>
-         <rect x="89" y="77" width="26" height="32" class="terminal" rx="10"/>
-         <text class="terminal" x="99" y="97">-</text><a xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#PropertyName" xlink:title="PropertyName">
-            <rect x="157" y="47" width="110" height="32"/>
-            <rect x="155" y="45" width="110" height="32" class="nonterminal"/>
-            <text class="nonterminal" x="165" y="65">PropertyName</text></a><a xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#PropertyName" xlink:title="PropertyName">
-            <rect x="71" y="123" width="110" height="32"/>
-            <rect x="69" y="121" width="110" height="32" class="nonterminal"/>
-            <text class="nonterminal" x="79" y="141">PropertyName</text></a><rect x="221" y="123" width="30" height="32" rx="10"/>
-         <rect x="219" y="121" width="30" height="32" class="terminal" rx="10"/>
-         <text class="terminal" x="229" y="141">=</text>
-         <rect x="221" y="167" width="34" height="32" rx="10"/>
-         <rect x="219" y="165" width="34" height="32" class="terminal" rx="10"/>
-         <text class="terminal" x="229" y="185">!=</text><a xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#Value" xlink:title="Value">
-            <rect x="295" y="123" width="56" height="32"/>
-            <rect x="293" y="121" width="56" height="32" class="nonterminal"/>
-            <text class="nonterminal" x="303" y="141">Value</text></a><rect x="51" y="3" width="24" height="32" rx="10"/>
+         <polygon points="17 61 9 57 9 65"/><a xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#PropertyQuery" xlink:title="PropertyQuery">
+            <rect x="51" y="47" width="112" height="32"/>
+            <rect x="49" y="45" width="112" height="32" class="nonterminal"/>
+            <text class="nonterminal" x="59" y="65">PropertyQuery</text></a><rect x="51" y="3" width="24" height="32" rx="10"/>
          <rect x="49" y="1" width="24" height="32" class="terminal" rx="10"/>
          <text class="terminal" x="59" y="21">,</text>
-         <svg:path xmlns:svg="http://www.w3.org/2000/svg" class="line" d="m17 61 h2 m60 0 h10 m0 0 h36 m-66 0 h20 m46 0 h20 m-86 0 q10 0 10 10 m66 0 q0 -10 10 -10 m-76 10 v12 m66 0 v-12 m-66 12 q0 10 10 10 m46 0 q10 0 10 -10 m-56 10 h10 m26 0 h10 m20 -32 h10 m110 0 h10 m0 0 h84 m-320 0 h20 m300 0 h20 m-340 0 q10 0 10 10 m320 0 q0 -10 10 -10 m-330 10 v56 m320 0 v-56 m-320 56 q0 10 10 10 m300 0 q10 0 10 -10 m-310 10 h10 m110 0 h10 m20 0 h10 m30 0 h10 m0 0 h4 m-74 0 h20 m54 0 h20 m-94 0 q10 0 10 10 m74 0 q0 -10 10 -10 m-84 10 v24 m74 0 v-24 m-74 24 q0 10 10 10 m54 0 q10 0 10 -10 m-64 10 h10 m34 0 h10 m20 -44 h10 m56 0 h10 m-340 -76 l20 0 m-1 0 q-9 0 -9 -10 l0 -24 q0 -10 10 -10 m340 44 l20 0 m-20 0 q10 0 10 -10 l0 -24 q0 -10 -10 -10 m-340 0 h10 m24 0 h10 m0 0 h296 m23 44 h-3"/>
-         <polygon points="409 61 417 57 417 65"/>
-         <polygon points="409 61 401 57 401 65"/></svg><xhtml:p xmlns:xhtml="http://www.w3.org/1999/xhtml">
+         <svg:path xmlns:svg="http://www.w3.org/2000/svg" class="line" d="m17 61 h2 m20 0 h10 m112 0 h10 m-152 0 l20 0 m-1 0 q-9 0 -9 -10 l0 -24 q0 -10 10 -10 m132 44 l20 0 m-20 0 q10 0 10 -10 l0 -24 q0 -10 -10 -10 m-132 0 h10 m24 0 h10 m0 0 h88 m23 44 h-3"/>
+         <polygon points="201 61 209 57 209 65"/>
+         <polygon points="201 61 193 57 193 65"/></svg><xhtml:p xmlns:xhtml="http://www.w3.org/1999/xhtml">
          <xhtml:div class="ebnf"><xhtml:code>
-               <div><a href="#Query" title="Query">Query</a>    ::= ( '-'? <a href="#PropertyName" title="PropertyName">PropertyName</a> | <a href="#PropertyName" title="PropertyName">PropertyName</a> ( '=' | '!=' ) <a href="#Value" title="Value">Value</a> ) ( ',' ( '-'? <a href="#PropertyName" title="PropertyName">PropertyName</a> | <a href="#PropertyName" title="PropertyName">PropertyName</a> ( '=' | '!=' ) <a href="#Value" title="Value">Value</a> ) )*</div></xhtml:code></xhtml:div>
+               <div><a href="#Query" title="Query">Query</a>    ::= <a href="#PropertyQuery" title="PropertyQuery">PropertyQuery</a> ( ',' <a href="#PropertyQuery" title="PropertyQuery">PropertyQuery</a> )*</div></xhtml:code></xhtml:div>
       </xhtml:p>
-      <xhtml:p xmlns:xhtml="http://www.w3.org/1999/xhtml">no references</xhtml:p><xhtml:br xmlns:xhtml="http://www.w3.org/1999/xhtml" /><xhtml:p xmlns:xhtml="http://www.w3.org/1999/xhtml" style="font-size: 14px; font-weight:bold"><xhtml:a name="Value">Value:</xhtml:a></xhtml:p><svg xmlns="http://www.w3.org/2000/svg" width="207" height="81">
+      <xhtml:p xmlns:xhtml="http://www.w3.org/1999/xhtml">no references</xhtml:p><xhtml:br xmlns:xhtml="http://www.w3.org/1999/xhtml" /><xhtml:p xmlns:xhtml="http://www.w3.org/1999/xhtml" style="font-size: 14px; font-weight:bold"><xhtml:a name="PropertyQuery">PropertyQuery:</xhtml:a></xhtml:p><svg xmlns="http://www.w3.org/2000/svg" width="465" height="189">
+         <defs>
+            <style type="text/css">
+    @namespace "http://www.w3.org/2000/svg";
+    .line                 {fill: none; stroke: #332900;}
+    .bold-line            {stroke: #141000; shape-rendering: crispEdges; stroke-width: 2; }
+    .thin-line            {stroke: #1F1800; shape-rendering: crispEdges}
+    .filled               {fill: #332900; stroke: none;}
+    text.terminal         {font-family: Verdana, Sans-serif;
+                            font-size: 12px;
+                            fill: #141000;
+                            font-weight: bold;
+                          }
+    text.nonterminal      {font-family: Verdana, Sans-serif;
+                            font-size: 12px;
+                            fill: #1A1400;
+                            font-weight: normal;
+                          }
+    text.regexp           {font-family: Verdana, Sans-serif;
+                            font-size: 12px;
+                            fill: #1F1800;
+                            font-weight: normal;
+                          }
+    rect, circle, polygon {fill: #332900; stroke: #332900;}
+    rect.terminal         {fill: #FFDB4D; stroke: #332900;}
+    rect.nonterminal      {fill: #FFEC9E; stroke: #332900;}
+    rect.text             {fill: none; stroke: none;}    
+    polygon.regexp        {fill: #FFF4C7; stroke: #332900;}
+  </style>
+         </defs>
+         <polygon points="9 17 1 13 1 21"/>
+         <polygon points="17 17 9 13 9 21"/>
+         <rect x="71" y="35" width="26" height="32" rx="10"/>
+         <rect x="69" y="33" width="26" height="32" class="terminal" rx="10"/>
+         <text class="terminal" x="79" y="53">-</text><a xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#PropertyName" xlink:title="PropertyName">
+            <rect x="137" y="3" width="110" height="32"/>
+            <rect x="135" y="1" width="110" height="32" class="nonterminal"/>
+            <text class="nonterminal" x="145" y="21">PropertyName</text></a><rect x="51" y="79" width="26" height="32" rx="10"/>
+         <rect x="49" y="77" width="26" height="32" class="terminal" rx="10"/>
+         <text class="terminal" x="59" y="97">?</text><a xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#PropertyName" xlink:title="PropertyName">
+            <rect x="97" y="79" width="110" height="32"/>
+            <rect x="95" y="77" width="110" height="32" class="nonterminal"/>
+            <text class="nonterminal" x="105" y="97">PropertyName</text></a><rect x="267" y="111" width="30" height="32" rx="10"/>
+         <rect x="265" y="109" width="30" height="32" class="terminal" rx="10"/>
+         <text class="terminal" x="275" y="129">=</text>
+         <rect x="267" y="155" width="34" height="32" rx="10"/>
+         <rect x="265" y="153" width="34" height="32" class="terminal" rx="10"/>
+         <text class="terminal" x="275" y="173">!=</text><a xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#Value" xlink:title="Value">
+            <rect x="341" y="111" width="56" height="32"/>
+            <rect x="339" y="109" width="56" height="32" class="nonterminal"/>
+            <text class="nonterminal" x="349" y="129">Value</text></a><svg:path xmlns:svg="http://www.w3.org/2000/svg" class="line" d="m17 17 h2 m40 0 h10 m0 0 h36 m-66 0 h20 m46 0 h20 m-86 0 q10 0 10 10 m66 0 q0 -10 10 -10 m-76 10 v12 m66 0 v-12 m-66 12 q0 10 10 10 m46 0 q10 0 10 -10 m-56 10 h10 m26 0 h10 m20 -32 h10 m110 0 h10 m0 0 h170 m-406 0 h20 m386 0 h20 m-426 0 q10 0 10 10 m406 0 q0 -10 10 -10 m-416 10 v56 m406 0 v-56 m-406 56 q0 10 10 10 m386 0 q10 0 10 -10 m-396 10 h10 m26 0 h10 m0 0 h10 m110 0 h10 m20 0 h10 m0 0 h160 m-190 0 h20 m170 0 h20 m-210 0 q10 0 10 10 m190 0 q0 -10 10 -10 m-200 10 v12 m190 0 v-12 m-190 12 q0 10 10 10 m170 0 q10 0 10 -10 m-160 10 h10 m30 0 h10 m0 0 h4 m-74 0 h20 m54 0 h20 m-94 0 q10 0 10 10 m74 0 q0 -10 10 -10 m-84 10 v24 m74 0 v-24 m-74 24 q0 10 10 10 m54 0 q10 0 10 -10 m-64 10 h10 m34 0 h10 m20 -44 h10 m56 0 h10 m43 -108 h-3"/>
+         <polygon points="455 17 463 13 463 21"/>
+         <polygon points="455 17 447 13 447 21"/></svg><xhtml:p xmlns:xhtml="http://www.w3.org/1999/xhtml">
+         <xhtml:div class="ebnf"><xhtml:code>
+               <div><a href="#PropertyQuery" title="PropertyQuery">PropertyQuery</a></div>
+               <div>         ::= '-'? <a href="#PropertyName" title="PropertyName">PropertyName</a></div>
+               <div>           | '?' <a href="#PropertyName" title="PropertyName">PropertyName</a> ( ( '=' | '!=' ) <a href="#Value" title="Value">Value</a> )?</div></xhtml:code></xhtml:div>
+      </xhtml:p>
+      <xhtml:p xmlns:xhtml="http://www.w3.org/1999/xhtml">referenced by:
+         <xhtml:ul>
+            <xhtml:li><xhtml:a href="#Query" title="Query">Query</xhtml:a></xhtml:li>
+         </xhtml:ul>
+      </xhtml:p><xhtml:br xmlns:xhtml="http://www.w3.org/1999/xhtml" /><xhtml:p xmlns:xhtml="http://www.w3.org/1999/xhtml" style="font-size: 14px; font-weight:bold"><xhtml:a name="Value">Value:</xhtml:a></xhtml:p><svg xmlns="http://www.w3.org/2000/svg" width="207" height="81">
          <defs>
             <style type="text/css">
     @namespace "http://www.w3.org/2000/svg";
       <xhtml:p xmlns:xhtml="http://www.w3.org/1999/xhtml">referenced by:
          <xhtml:ul>
             <xhtml:li><xhtml:a href="#Definition" title="Definition">Definition</xhtml:a></xhtml:li>
-            <xhtml:li><xhtml:a href="#Query" title="Query">Query</xhtml:a></xhtml:li>
+            <xhtml:li><xhtml:a href="#PropertyQuery" title="PropertyQuery">PropertyQuery</xhtml:a></xhtml:li>
          </xhtml:ul>
       </xhtml:p><xhtml:br xmlns:xhtml="http://www.w3.org/1999/xhtml" /><xhtml:p xmlns:xhtml="http://www.w3.org/1999/xhtml" style="font-size: 14px; font-weight:bold"><xhtml:a name="StringLiteral">StringLiteral:</xhtml:a></xhtml:p><svg xmlns="http://www.w3.org/2000/svg" width="219" height="81">
          <defs>
       <xhtml:p xmlns:xhtml="http://www.w3.org/1999/xhtml">referenced by:
          <xhtml:ul>
             <xhtml:li><xhtml:a href="#Definition" title="Definition">Definition</xhtml:a></xhtml:li>
-            <xhtml:li><xhtml:a href="#Query" title="Query">Query</xhtml:a></xhtml:li>
+            <xhtml:li><xhtml:a href="#PropertyQuery" title="PropertyQuery">PropertyQuery</xhtml:a></xhtml:li>
          </xhtml:ul>
       </xhtml:p><xhtml:br xmlns:xhtml="http://www.w3.org/1999/xhtml" /><xhtml:hr xmlns:xhtml="http://www.w3.org/1999/xhtml" />
       <xhtml:p xmlns:xhtml="http://www.w3.org/1999/xhtml">
index 930c89bf4869f2dc5618f19633f9799e6db81279..9dd8f6a3ff8b0ccf7af19561c2a1a447ad0d154d 100644 (file)
@@ -277,7 +277,7 @@ int ossl_method_store_fetch(OSSL_METHOD_STORE *store, int nid,
     IMPLEMENTATION *impl;
     OSSL_PROPERTY_LIST *pq = NULL, *p2;
     int ret = 0;
-    int j;
+    int j, best = -1, score, optional;
 
     if (nid <= 0 || method == NULL || store == NULL)
         return 0;
@@ -310,13 +310,16 @@ int ossl_method_store_fetch(OSSL_METHOD_STORE *store, int nid,
         ossl_property_free(pq);
         pq = p2;
     }
+    optional = ossl_property_has_optional(pq);
     for (j = 0; j < sk_IMPLEMENTATION_num(alg->impls); j++) {
         impl = sk_IMPLEMENTATION_value(alg->impls, j);
-
-        if (ossl_property_match(pq, impl->properties)) {
+        score = ossl_property_match_count(pq, impl->properties);
+        if (score > best) {
             *method = impl->method;
             ret = 1;
-            goto fin;
+            if (!optional)
+                goto fin;
+            best = score;
         }
     }
 fin:
index 304dc22ad91f034df053f638cb4984d09eccbdc4..5fa34cea8228f6023c2ff321c92791eddf18ff09 100644 (file)
@@ -23,8 +23,9 @@ OSSL_PROPERTY_IDX ossl_property_value(OPENSSL_CTX *ctx, const char *s,
 /* Property list functions */
 int ossl_property_parse_init(OPENSSL_CTX *ctx);
 void ossl_property_free(OSSL_PROPERTY_LIST *p);
-int ossl_property_match(const OSSL_PROPERTY_LIST *query,
-                        const OSSL_PROPERTY_LIST *defn);
+int ossl_property_has_optional(const OSSL_PROPERTY_LIST *query);
+int ossl_property_match_count(const OSSL_PROPERTY_LIST *query,
+                              const OSSL_PROPERTY_LIST *defn);
 OSSL_PROPERTY_LIST *ossl_property_merge(const OSSL_PROPERTY_LIST *a,
                                         const OSSL_PROPERTY_LIST *b);
 
index efc459a919e31edb7555d759ee4574a3e129fb7f..c63a433ddbe2d50df637751516901f65883e8358 100644 (file)
@@ -32,6 +32,7 @@ typedef struct {
     OSSL_PROPERTY_IDX name_idx;
     PROPERTY_TYPE type;
     PROPERTY_OPER oper;
+    unsigned int optional : 1;
     union {
         int64_t             int_val;     /* Signed integer */
         OSSL_PROPERTY_IDX   str_val;     /* String */
@@ -40,6 +41,7 @@ typedef struct {
 
 struct ossl_property_list_st {
     int n;
+    unsigned int has_optional : 1;
     PROPERTY_DEFINITION properties[1];
 };
 
@@ -307,8 +309,11 @@ static OSSL_PROPERTY_LIST *stack_to_property_list(STACK_OF(PROPERTY_DEFINITION)
     if (r != NULL) {
         sk_PROPERTY_DEFINITION_sort(sk);
 
-        for (i = 0; i < n; i++)
+        r->has_optional = 0;
+        for (i = 0; i < n; i++) {
             r->properties[i] = *sk_PROPERTY_DEFINITION_value(sk, i);
+            r->has_optional |= r->properties[i].optional;
+        }
         r->n = n;
     }
     return r;
@@ -332,6 +337,7 @@ OSSL_PROPERTY_LIST *ossl_parse_property(OPENSSL_CTX *ctx, const char *defn)
         if (prop == NULL)
             goto err;
         memset(&prop->v, 0, sizeof(prop->v));
+        prop->optional = 0;
         if (!parse_name(ctx, &s, 1, &prop->name_idx))
             goto err;
         prop->oper = PROPERTY_OPER_EQ;
@@ -387,10 +393,12 @@ OSSL_PROPERTY_LIST *ossl_parse_query(OPENSSL_CTX *ctx, const char *s)
 
         if (match_ch(&s, '-')) {
             prop->oper = PROPERTY_OVERRIDE;
+            prop->optional = 0;
             if (!parse_name(ctx, &s, 0, &prop->name_idx))
                 goto err;
             goto skip_value;
         }
+        prop->optional = match_ch(&s, '?');
         if (!parse_name(ctx, &s, 0, &prop->name_idx))
             goto err;
 
@@ -426,12 +434,22 @@ err:
     return res;
 }
 
-int ossl_property_match(const OSSL_PROPERTY_LIST *query,
-                        const OSSL_PROPERTY_LIST *defn)
+/* Does a property query have any optional clauses */
+int ossl_property_has_optional(const OSSL_PROPERTY_LIST *query)
+{
+    return query->has_optional ? 1 : 0;
+}
+
+/*
+ * Compare a query against a definition.
+ * Return the number of clauses matched or -1 if a mandatory clause is false.
+ */
+int ossl_property_match_count(const OSSL_PROPERTY_LIST *query,
+                              const OSSL_PROPERTY_LIST *defn)
 {
     const PROPERTY_DEFINITION *const q = query->properties;
     const PROPERTY_DEFINITION *const d = defn->properties;
-    int i = 0, j = 0;
+    int i = 0, j = 0, matches = 0;
     PROPERTY_OPER oper;
 
     while (i < query->n) {
@@ -448,9 +466,11 @@ int ossl_property_match(const OSSL_PROPERTY_LIST *query,
                 const int eq = q[i].type == d[j].type
                                && memcmp(&q[i].v, &d[j].v, sizeof(q[i].v)) == 0;
 
-                if ((eq && oper != PROPERTY_OPER_EQ)
-                    || (!eq && oper != PROPERTY_OPER_NE))
-                    return 0;
+                if ((eq && oper == PROPERTY_OPER_EQ)
+                    || (!eq && oper == PROPERTY_OPER_NE))
+                    matches++;
+                else if (!q[i].optional)
+                    return -1;
                 i++;
                 j++;
                 continue;
@@ -463,18 +483,23 @@ int ossl_property_match(const OSSL_PROPERTY_LIST *query,
          * the latter is treated as a comparison against the Boolean false.
          */
         if (q[i].type == PROPERTY_TYPE_VALUE_UNDEFINED) {
-            if (oper != PROPERTY_OPER_NE)
-                return 0;
+            if (oper == PROPERTY_OPER_NE)
+                matches++;
+            else if (!q[i].optional)
+                return -1;
         } else if (q[i].type != PROPERTY_TYPE_STRING
                    || (oper == PROPERTY_OPER_EQ
                        && q[i].v.str_val != ossl_property_false)
                    || (oper == PROPERTY_OPER_NE
                        && q[i].v.str_val == ossl_property_false)) {
-            return 0;
+            if (!q[i].optional)
+                return -1;
+        } else {
+            matches++;
         }
         i++;
     }
-    return 1;
+    return matches;
 }
 
 void ossl_property_free(OSSL_PROPERTY_LIST *p)
index 7ec40d6e51d5c1694b47bfde4d75a1c0e676da85..765416a11d80d9b08cede91ebe822d82dfad136c 100644 (file)
@@ -62,31 +62,36 @@ static const struct {
     const char *query;
     int e;
 } parser_tests[] = {
-    { "", "sky=blue", 0 },
+    { "", "sky=blue", -1 },
     { "", "sky!=blue", 1 },
-    { "groan", "", 1 },
+    { "groan", "", 0 },
     { "cold=yes", "cold=yes", 1 },
     { "cold=yes", "cold", 1 },
     { "cold=yes", "cold!=no", 1 },
     { "groan", "groan=yes", 1 },
-    { "groan", "groan=no", 0 },
-    { "groan", "groan!=yes", 0 },
-    { "cold=no", "cold", 0 },
+    { "groan", "groan=no", -1 },
+    { "groan", "groan!=yes", -1 },
+    { "cold=no", "cold", -1 },
+    { "cold=no", "?cold", 0 },
     { "cold=no", "cold=no", 1 },
-    { "groan", "cold", 0 },
+    { "groan", "cold", -1 },
     { "groan", "cold=no", 1 },
     { "groan", "cold!=yes", 1 },
-    { "groan=blue", "groan=yellow", 0 },
+    { "groan=blue", "groan=yellow", -1 },
+    { "groan=blue", "?groan=yellow", 0 },
     { "groan=blue", "groan!=yellow", 1 },
+    { "groan=blue", "?groan!=yellow", 1 },
     { "today=monday, tomorrow=3", "today!=2", 1 },
-    { "today=monday, tomorrow=3", "today!='monday'", 0 },
+    { "today=monday, tomorrow=3", "today!='monday'", -1 },
     { "today=monday, tomorrow=3", "tomorrow=3", 1 },
     { "n=0x3", "n=3", 1 },
-    { "n=0x3", "n=-3", 0 },
+    { "n=0x3", "n=-3", -1 },
     { "n=0x33", "n=51", 1 },
     { "n=033", "n=27", 1 },
     { "n=0", "n=00", 1 },
     { "n=0x0", "n=0", 1 },
+    { "n=0, sky=blue", "?n=0, sky=blue", 2 },
+    { "n=1, sky=blue", "?n=0, sky=blue", 1 },
 };
 
 static int test_property_parse(int n)
@@ -100,7 +105,7 @@ static int test_property_parse(int n)
                               NULL)
         && TEST_ptr(p = ossl_parse_property(NULL, parser_tests[n].defn))
         && TEST_ptr(q = ossl_parse_query(NULL, parser_tests[n].query))
-        && TEST_int_eq(ossl_property_match(q, p), parser_tests[n].e))
+        && TEST_int_eq(ossl_property_match_count(q, p), parser_tests[n].e))
         r = 1;
     ossl_property_free(p);
     ossl_property_free(q);
@@ -148,7 +153,7 @@ static int test_property_merge(int n)
         && TEST_ptr(q_global = ossl_parse_query(NULL, merge_tests[n].q_global))
         && TEST_ptr(q_local = ossl_parse_query(NULL, merge_tests[n].q_local))
         && TEST_ptr(q_combined = ossl_property_merge(q_local, q_global))
-        && TEST_true(ossl_property_match(q_combined, prop)))
+        && TEST_int_ge(ossl_property_match_count(q_combined, prop), 0))
         r = 1;
     ossl_property_free(q_global);
     ossl_property_free(q_local);
@@ -184,10 +189,16 @@ static const struct {
     int e;
 } definition_tests[] = {
     { "alpha", "alpha=yes", 1 },
-    { "alpha=no", "alpha", 0 },
+    { "alpha=no", "alpha", -1 },
     { "alpha=1", "alpha=1", 1 },
-    { "alpha=2", "alpha=1", 0 },
-    { "alpha", "omega", 0 }
+    { "alpha=2", "alpha=1",-1 },
+    { "alpha", "omega", -1 },
+    { "alpha", "?omega", 0 },
+    { "alpha", "?omega=1", 0 },
+    { "alpha", "?omega=no", 1 },
+    { "alpha", "?omega=yes", 0 },
+    { "alpha, omega", "?omega=yes", 1 },
+    { "alpha, omega", "?omega=no", 0 }
 };
 
 static int test_definition_compares(int n)
@@ -200,7 +211,7 @@ static int test_definition_compares(int n)
         && add_property_names("alpha", "omega", NULL)
         && TEST_ptr(d = ossl_parse_property(NULL, definition_tests[n].defn))
         && TEST_ptr(q = ossl_parse_query(NULL, definition_tests[n].query))
-        && TEST_int_eq(ossl_property_match(q, d), definition_tests[n].e);
+        && TEST_int_eq(ossl_property_match_count(q, d), definition_tests[n].e);
 
     ossl_property_free(d);
     ossl_property_free(q);