[Commits] 294d9bf: MDEV-5313 Improving audit api.

Alexey Botchkov holyfoot at askmonty.org
Thu Jan 17 01:54:41 EET 2019


revision-id: 294d9bf2484abfd3409d4ac25a3b3b695d66b0ec (mariadb-10.4.1-93-g294d9bf)
parent(s): edba0470803bf2277b5509af3b978f042c0b7204
committer: Alexey Botchkov
timestamp: 2019-01-17 03:52:52 +0400
message:

MDEV-5313 Improving audit api.

JSON api implementations and tests pushed.
sql_acl.cc fixed with the new function names.

---
 include/json_lib.h                            |   4 -
 include/mysql/plugin_audit.h.pp               |  20 ++--
 include/mysql/plugin_auth.h.pp                |  20 ++--
 include/mysql/plugin_encryption.h.pp          |  20 ++--
 include/mysql/plugin_ftparser.h.pp            |  20 ++--
 include/mysql/plugin_password_validation.h.pp |  20 ++--
 include/mysql/service_json.h                  |  20 ++--
 sql/sql_acl.cc                                |  30 +++---
 strings/json_lib.c                            | 145 +++++++++++++++++---------
 unittest/strings/CMakeLists.txt               |   2 +-
 10 files changed, 174 insertions(+), 127 deletions(-)

diff --git a/include/json_lib.h b/include/json_lib.h
index 0f8cff7..a347538 100644
--- a/include/json_lib.h
+++ b/include/json_lib.h
@@ -425,10 +425,6 @@ int json_path_compare(const json_path_t *a, const json_path_t *b,
 
 int json_valid(const char *js, size_t js_len, CHARSET_INFO *cs);
 
-int json_get_object_by_key(const char *js, size_t js_len,
-                           const char *key, size_t key_len,
-                           enum json_value_types *value_type,
-                           const char **value_start, size_t *value_len);
 #ifdef  __cplusplus
 }
 #endif
diff --git a/include/mysql/plugin_audit.h.pp b/include/mysql/plugin_audit.h.pp
index 0588b21..47f07ae 100644
--- a/include/mysql/plugin_audit.h.pp
+++ b/include/mysql/plugin_audit.h.pp
@@ -388,33 +388,33 @@ enum json_types
 };
 extern struct json_service_st {
   enum json_types (*json_type)(const char *js, const char *js_end,
-                               const char **v, int *vlen);
+                               const char **value, int *value_len);
   enum json_types (*json_get_array_item)(const char *js, const char *js_end,
                                          int n_item,
-                                         const char **v, int *vlen);
+                                         const char **value, int *value_len);
   enum json_types (*json_get_object_key)(const char *js, const char *js_end,
-                                         const char *key,
-                                         const char **v, int *vlen);
+                                         const char *key, const char *key_end,
+                                         const char **value, int *value_len);
   enum json_types (*json_get_object_nkey)(const char *js,const char *js_end,
                              int nkey,
                              const char **keyname, const char **keyname_end,
-                             const char **v, int *vlen);
+                             const char **value, int *value_len);
   int (*json_escape_string)(const char *str,const char *str_end,
                           char *json, char *json_end);
   int (*json_unescape_json)(const char *json_str, const char *json_end,
                           char *res, char *res_end);
 } *json_service;
 enum json_types json_type(const char *js, const char *js_end,
-                          const char **v, int *vlen);
+                          const char **value, int *value_len);
 enum json_types json_get_array_item(const char *js, const char *js_end,
                                     int n_item,
-                                    const char **v, int *vlen);
+                                    const char **value, int *value_len);
 enum json_types json_get_object_key(const char *js, const char *js_end,
-                                    const char *key,
-                                    const char **v, int *vlen);
+                                    const char *key, const char *key_end,
+                                    const char **value, int *value_len);
 enum json_types json_get_object_nkey(const char *js,const char *js_end, int nkey,
                        const char **keyname, const char **keyname_end,
-                       const char **v, int *vlen);
+                       const char **value, int *value_len);
 int json_escape_string(const char *str,const char *str_end,
                        char *json, char *json_end);
 int json_unescape_json(const char *json_str, const char *json_end,
diff --git a/include/mysql/plugin_auth.h.pp b/include/mysql/plugin_auth.h.pp
index cfb9201..f9d01a8 100644
--- a/include/mysql/plugin_auth.h.pp
+++ b/include/mysql/plugin_auth.h.pp
@@ -388,33 +388,33 @@ enum json_types
 };
 extern struct json_service_st {
   enum json_types (*json_type)(const char *js, const char *js_end,
-                               const char **v, int *vlen);
+                               const char **value, int *value_len);
   enum json_types (*json_get_array_item)(const char *js, const char *js_end,
                                          int n_item,
-                                         const char **v, int *vlen);
+                                         const char **value, int *value_len);
   enum json_types (*json_get_object_key)(const char *js, const char *js_end,
-                                         const char *key,
-                                         const char **v, int *vlen);
+                                         const char *key, const char *key_end,
+                                         const char **value, int *value_len);
   enum json_types (*json_get_object_nkey)(const char *js,const char *js_end,
                              int nkey,
                              const char **keyname, const char **keyname_end,
-                             const char **v, int *vlen);
+                             const char **value, int *value_len);
   int (*json_escape_string)(const char *str,const char *str_end,
                           char *json, char *json_end);
   int (*json_unescape_json)(const char *json_str, const char *json_end,
                           char *res, char *res_end);
 } *json_service;
 enum json_types json_type(const char *js, const char *js_end,
-                          const char **v, int *vlen);
+                          const char **value, int *value_len);
 enum json_types json_get_array_item(const char *js, const char *js_end,
                                     int n_item,
-                                    const char **v, int *vlen);
+                                    const char **value, int *value_len);
 enum json_types json_get_object_key(const char *js, const char *js_end,
-                                    const char *key,
-                                    const char **v, int *vlen);
+                                    const char *key, const char *key_end,
+                                    const char **value, int *value_len);
 enum json_types json_get_object_nkey(const char *js,const char *js_end, int nkey,
                        const char **keyname, const char **keyname_end,
-                       const char **v, int *vlen);
+                       const char **value, int *value_len);
 int json_escape_string(const char *str,const char *str_end,
                        char *json, char *json_end);
 int json_unescape_json(const char *json_str, const char *json_end,
diff --git a/include/mysql/plugin_encryption.h.pp b/include/mysql/plugin_encryption.h.pp
index 7761a3e..e55a034 100644
--- a/include/mysql/plugin_encryption.h.pp
+++ b/include/mysql/plugin_encryption.h.pp
@@ -388,33 +388,33 @@ enum json_types
 };
 extern struct json_service_st {
   enum json_types (*json_type)(const char *js, const char *js_end,
-                               const char **v, int *vlen);
+                               const char **value, int *value_len);
   enum json_types (*json_get_array_item)(const char *js, const char *js_end,
                                          int n_item,
-                                         const char **v, int *vlen);
+                                         const char **value, int *value_len);
   enum json_types (*json_get_object_key)(const char *js, const char *js_end,
-                                         const char *key,
-                                         const char **v, int *vlen);
+                                         const char *key, const char *key_end,
+                                         const char **value, int *value_len);
   enum json_types (*json_get_object_nkey)(const char *js,const char *js_end,
                              int nkey,
                              const char **keyname, const char **keyname_end,
-                             const char **v, int *vlen);
+                             const char **value, int *value_len);
   int (*json_escape_string)(const char *str,const char *str_end,
                           char *json, char *json_end);
   int (*json_unescape_json)(const char *json_str, const char *json_end,
                           char *res, char *res_end);
 } *json_service;
 enum json_types json_type(const char *js, const char *js_end,
-                          const char **v, int *vlen);
+                          const char **value, int *value_len);
 enum json_types json_get_array_item(const char *js, const char *js_end,
                                     int n_item,
-                                    const char **v, int *vlen);
+                                    const char **value, int *value_len);
 enum json_types json_get_object_key(const char *js, const char *js_end,
-                                    const char *key,
-                                    const char **v, int *vlen);
+                                    const char *key, const char *key_end,
+                                    const char **value, int *value_len);
 enum json_types json_get_object_nkey(const char *js,const char *js_end, int nkey,
                        const char **keyname, const char **keyname_end,
-                       const char **v, int *vlen);
+                       const char **value, int *value_len);
 int json_escape_string(const char *str,const char *str_end,
                        char *json, char *json_end);
 int json_unescape_json(const char *json_str, const char *json_end,
diff --git a/include/mysql/plugin_ftparser.h.pp b/include/mysql/plugin_ftparser.h.pp
index 2e77597..f9d9844 100644
--- a/include/mysql/plugin_ftparser.h.pp
+++ b/include/mysql/plugin_ftparser.h.pp
@@ -388,33 +388,33 @@ enum json_types
 };
 extern struct json_service_st {
   enum json_types (*json_type)(const char *js, const char *js_end,
-                               const char **v, int *vlen);
+                               const char **value, int *value_len);
   enum json_types (*json_get_array_item)(const char *js, const char *js_end,
                                          int n_item,
-                                         const char **v, int *vlen);
+                                         const char **value, int *value_len);
   enum json_types (*json_get_object_key)(const char *js, const char *js_end,
-                                         const char *key,
-                                         const char **v, int *vlen);
+                                         const char *key, const char *key_end,
+                                         const char **value, int *value_len);
   enum json_types (*json_get_object_nkey)(const char *js,const char *js_end,
                              int nkey,
                              const char **keyname, const char **keyname_end,
-                             const char **v, int *vlen);
+                             const char **value, int *value_len);
   int (*json_escape_string)(const char *str,const char *str_end,
                           char *json, char *json_end);
   int (*json_unescape_json)(const char *json_str, const char *json_end,
                           char *res, char *res_end);
 } *json_service;
 enum json_types json_type(const char *js, const char *js_end,
-                          const char **v, int *vlen);
+                          const char **value, int *value_len);
 enum json_types json_get_array_item(const char *js, const char *js_end,
                                     int n_item,
-                                    const char **v, int *vlen);
+                                    const char **value, int *value_len);
 enum json_types json_get_object_key(const char *js, const char *js_end,
-                                    const char *key,
-                                    const char **v, int *vlen);
+                                    const char *key, const char *key_end,
+                                    const char **value, int *value_len);
 enum json_types json_get_object_nkey(const char *js,const char *js_end, int nkey,
                        const char **keyname, const char **keyname_end,
-                       const char **v, int *vlen);
+                       const char **value, int *value_len);
 int json_escape_string(const char *str,const char *str_end,
                        char *json, char *json_end);
 int json_unescape_json(const char *json_str, const char *json_end,
diff --git a/include/mysql/plugin_password_validation.h.pp b/include/mysql/plugin_password_validation.h.pp
index 7492642..b672db6 100644
--- a/include/mysql/plugin_password_validation.h.pp
+++ b/include/mysql/plugin_password_validation.h.pp
@@ -388,33 +388,33 @@ enum json_types
 };
 extern struct json_service_st {
   enum json_types (*json_type)(const char *js, const char *js_end,
-                               const char **v, int *vlen);
+                               const char **value, int *value_len);
   enum json_types (*json_get_array_item)(const char *js, const char *js_end,
                                          int n_item,
-                                         const char **v, int *vlen);
+                                         const char **value, int *value_len);
   enum json_types (*json_get_object_key)(const char *js, const char *js_end,
-                                         const char *key,
-                                         const char **v, int *vlen);
+                                         const char *key, const char *key_end,
+                                         const char **value, int *value_len);
   enum json_types (*json_get_object_nkey)(const char *js,const char *js_end,
                              int nkey,
                              const char **keyname, const char **keyname_end,
-                             const char **v, int *vlen);
+                             const char **value, int *value_len);
   int (*json_escape_string)(const char *str,const char *str_end,
                           char *json, char *json_end);
   int (*json_unescape_json)(const char *json_str, const char *json_end,
                           char *res, char *res_end);
 } *json_service;
 enum json_types json_type(const char *js, const char *js_end,
-                          const char **v, int *vlen);
+                          const char **value, int *value_len);
 enum json_types json_get_array_item(const char *js, const char *js_end,
                                     int n_item,
-                                    const char **v, int *vlen);
+                                    const char **value, int *value_len);
 enum json_types json_get_object_key(const char *js, const char *js_end,
-                                    const char *key,
-                                    const char **v, int *vlen);
+                                    const char *key, const char *key_end,
+                                    const char **value, int *value_len);
 enum json_types json_get_object_nkey(const char *js,const char *js_end, int nkey,
                        const char **keyname, const char **keyname_end,
-                       const char **v, int *vlen);
+                       const char **value, int *value_len);
 int json_escape_string(const char *str,const char *str_end,
                        char *json, char *json_end);
 int json_unescape_json(const char *json_str, const char *json_end,
diff --git a/include/mysql/service_json.h b/include/mysql/service_json.h
index 2044172..734787a 100644
--- a/include/mysql/service_json.h
+++ b/include/mysql/service_json.h
@@ -61,17 +61,17 @@ enum json_types
 
 extern struct json_service_st {
   enum json_types (*json_type)(const char *js, const char *js_end,
-                               const char **v, int *vlen);
+                               const char **value, int *value_len);
   enum json_types (*json_get_array_item)(const char *js, const char *js_end,
                                          int n_item,
-                                         const char **v, int *vlen);
+                                         const char **value, int *value_len);
   enum json_types (*json_get_object_key)(const char *js, const char *js_end,
-                                         const char *key,
-                                         const char **v, int *vlen);
+                                         const char *key, const char *key_end,
+                                         const char **value, int *value_len);
   enum json_types (*json_get_object_nkey)(const char *js,const char *js_end,
                              int nkey,
                              const char **keyname, const char **keyname_end,
-                             const char **v, int *vlen);
+                             const char **value, int *value_len);
   int (*json_escape_string)(const char *str,const char *str_end,
                           char *json, char *json_end);
   int (*json_unescape_json)(const char *json_str, const char *json_end,
@@ -90,16 +90,16 @@ extern struct json_service_st {
 #else
 
 enum json_types json_type(const char *js, const char *js_end,
-                          const char **v, int *vlen);
+                          const char **value, int *value_len);
 enum json_types json_get_array_item(const char *js, const char *js_end,
                                     int n_item,
-                                    const char **v, int *vlen);
+                                    const char **value, int *value_len);
 enum json_types json_get_object_key(const char *js, const char *js_end,
-                                    const char *key,
-                                    const char **v, int *vlen);
+                                    const char *key, const char *key_end,
+                                    const char **value, int *value_len);
 enum json_types json_get_object_nkey(const char *js,const char *js_end, int nkey,
                        const char **keyname, const char **keyname_end,
-                       const char **v, int *vlen);
+                       const char **value, int *value_len);
 int json_escape_string(const char *str,const char *str_end,
                        char *json, char *json_end);
 int json_unescape_json(const char *json_str, const char *json_end,
diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc
index b2840c3..61d6812 100644
--- a/sql/sql_acl.cc
+++ b/sql/sql_acl.cc
@@ -1291,20 +1291,23 @@ class User_table_json: public User_table
     return 0;
   }
   bool get_value(const char *key, size_t klen,
-                 enum json_value_types vt, const char **v, size_t *vl) const
+                 enum json_types vt, const char **v, size_t *vl) const
   {
-    enum json_value_types value_type;
+    enum json_types value_type;
+    int int_vl;
     String str, *res= m_table->field[2]->val_str(&str);
-    if (!res || json_get_object_by_key(res->ptr(), res->length(), key, klen,
-                                       &value_type, v, vl))
+    if (!res ||
+        (value_type= json_get_object_key(res->ptr(), res->end(),
+                             key, key+klen, v, &int_vl)) == JSV_BAD_JSON)
       return 1; // invalid
+    *vl= int_vl;
     return value_type != vt;
   }
   const char *get_str_value(MEM_ROOT *root, const char *key, size_t klen) const
   {
     size_t value_len;
     const char *value_start;
-    if (get_value(key, klen, JSON_VALUE_STRING, &value_start, &value_len))
+    if (get_value(key, klen, JSV_STRING, &value_start, &value_len))
       return "";
     char *ptr= (char*)alloca(value_len);
     int len= json_unescape(m_table->field[2]->charset(),
@@ -1321,7 +1324,7 @@ class User_table_json: public User_table
     int err;
     size_t value_len;
     const char *value_start;
-    if (get_value(key, klen, JSON_VALUE_NUMBER, &value_start, &value_len))
+    if (get_value(key, klen, JSV_NUMBER, &value_start, &value_len))
       return 0;
     const char *value_end= value_start + value_len;
     return my_strtoll10(value_start, (char**)&value_end, &err);
@@ -1331,7 +1334,7 @@ class User_table_json: public User_table
     int err;
     size_t value_len;
     const char *value_start;
-    if (get_value(key, klen, JSON_VALUE_NUMBER, &value_start, &value_len))
+    if (get_value(key, klen, JSV_NUMBER, &value_start, &value_len))
       return 0;
     const char *value_end= value_start + value_len;
     return my_strtod(value_start, (char**)&value_end, &err);
@@ -1340,25 +1343,26 @@ class User_table_json: public User_table
   {
     size_t value_len;
     const char *value_start;
-    if (get_value(key, klen, JSON_VALUE_TRUE, &value_start, &value_len))
+    if (get_value(key, klen, JSV_TRUE, &value_start, &value_len))
       return false;
     return true;
   }
   bool set_value(const char *key, size_t klen,
                  const char *val, size_t vlen, bool string) const
   {
-    size_t value_len;
+    int value_len;
     const char *value_start;
-    enum json_value_types value_type;
+    enum json_types value_type;
     String str, *res= m_table->field[2]->val_str(&str);
     if (!res || !res->length())
       (res= &str)->set(STRING_WITH_LEN("{}"), m_table->field[2]->charset());
-    if (json_get_object_by_key(res->ptr(), res->length(), key, klen,
-                               &value_type, &value_start, &value_len))
+    value_type= json_get_object_key(res->ptr(), res->end(), key, key+klen,
+                                    &value_start, &value_len);
+    if (value_type == JSV_BAD_JSON)
       return 1; // invalid
     StringBuffer<JSON_SIZE> json(res->charset());
     json.copy(res->ptr(), value_start - res->ptr(), res->charset());
-    if (!value_type)
+    if (value_type == JSV_NOTHING)
     {
       if (value_len)
         json.append(',');
diff --git a/strings/json_lib.c b/strings/json_lib.c
index bc93601..8930581 100644
--- a/strings/json_lib.c
+++ b/strings/json_lib.c
@@ -1847,57 +1847,104 @@ int json_path_compare(const json_path_t *a, const json_path_t *b,
 }
 
 
+static enum json_types smart_read_value(json_engine_t *je,
+                                        const char **value, int *value_len)
+{
+  if (json_read_value(je))
+    goto err_return;
+
+  *value= (char *) je->value;
+
+  if (json_value_scalar(je))
+    *value_len= je->value_len;
+  else
+  {
+    if (json_skip_level(je))
+      goto err_return;
+
+    *value_len= (char *) je->s.c_str - *value;
+  }
+
+  return je->value_type;
+
+err_return:
+  return JSV_BAD_JSON;
+}
+
+
 enum json_types json_type(const char *js, const char *js_end,
-                          const char **v, int *vlen)
+                          const char **value, int *value_len)
 {
-  return JSV_NOTHING;
+  json_engine_t je;
+
+  json_scan_start(&je, &my_charset_utf8mb4_bin,(const uchar *) js,
+                  (const uchar *) js_end);
+
+  return smart_read_value(&je, value, value_len);
 }
 
 
 enum json_types json_get_array_item(const char *js, const char *js_end,
                                     int n_item,
-                                    const char **v, int *vlen)
+                                    const char **value, int *value_len)
 {
-  return JSV_NOTHING;
-}
+  json_engine_t je;
+  int c_item= 0;
 
+  json_scan_start(&je, &my_charset_utf8mb4_bin,(const uchar *) js,
+                  (const uchar *) js_end);
 
-enum json_types json_get_object_key(const char *js, const char *js_end,
-                                    const char *key,
-                                    const char **v, int *vlen)
-{
-  return JSV_NOTHING;
-}
+  if (json_read_value(&je) ||
+      je.value_type != JSON_VALUE_ARRAY)
+    goto err_return;
 
+  while (!json_scan_next(&je))
+  {
+    switch (je.state)
+    {
+    case JST_VALUE:
+      if (c_item == n_item)
+        return smart_read_value(&je, value, value_len);
 
-enum json_types json_get_object_nkey(const char *js,const char *js_end, int nkey,
-                       const char **keyname, const char **keyname_end,
-                       const char **v, int *vlen)
-{
-  return JSV_NOTHING;
+      if (json_skip_key(&je))
+        goto err_return;
+
+      c_item++;
+      break;
+
+    case JST_ARRAY_END:
+      *value= (const char *) (je.s.c_str - je.sav_c_len);
+      *value_len= c_item;
+      return JSV_NOTHING;
+    }
+  }
+
+err_return:
+  return JSV_BAD_JSON;
 }
 
+
 /** Simple json lookup for a value by the key.
 
-  Only supports flat json objects.
-  Does not look inside nested objects.
-  Does not process complex path expressions.
+  Expects JSON object.
+  Only scans the 'first level' of the object, not
+  the nested structures.
 
-  @param js          [in]       json to search in
-  @param js_len      [in]         - " -
+  @param js          [in]       json object to search in
+  @param js_end      [in]       end of json string
   @param key         [in]       key to search for
-  @param key_len     [in]         - " -
-  @param value_type  [out]      type of the value found or 0 if not found
+  @param key_end     [in]         - " -
   @param value_start [out]      pointer into js (value or closing })
   @param value_len   [out]      length of the value found or number of keys
 
-  @retval 0 - success
-  @retval 1 - error (invalid json)
+  @retval the type of the key value
+  @retval JSV_BAD_JSON - syntax error found reading JSON.
+                         or not JSON object.
+  @retval JSV_NOTHING - no such key found.
 */
-int json_get_object_by_key(const char *js, size_t js_len,
-                           const char *key, size_t key_len,
-                           enum json_value_types *value_type,
-                           const char **value_start, size_t *value_len)
+enum json_types json_get_object_key(const char *js, const char *js_end,
+                                    const char *key, const char *key_end,
+                                    const char **value, int *value_len)
 {
   json_engine_t je;
   json_string_t key_name;
@@ -1906,7 +1953,7 @@ int json_get_object_by_key(const char *js, size_t js_len,
   json_string_set_cs(&key_name, &my_charset_utf8mb4_bin);
 
   json_scan_start(&je, &my_charset_utf8mb4_bin,(const uchar *) js,
-                  (const uchar *) js + js_len);
+                  (const uchar *) js_end);
 
   if (json_read_value(&je) ||
       je.value_type != JSON_VALUE_OBJECT)
@@ -1919,35 +1966,35 @@ int json_get_object_by_key(const char *js, size_t js_len,
     case JST_KEY:
       n_keys++;
       json_string_set_str(&key_name, (const uchar *) key,
-                          (const uchar *) key + key_len);
-      if (!json_key_matches(&je, &key_name))
-      {
-        if (json_skip_key(&je))
-          goto err_return;
-      }
-      else
-      {
-        if (json_read_value(&je))
-          goto err_return;
-        *value_type= je.value_type;
-        *value_start= (const char *) je.value;
-        *value_len= je.value_len;
-        return 0;
-      }
+                          (const uchar *) key_end);
+      if (json_key_matches(&je, &key_name))
+        return smart_read_value(&je, value, value_len);
+
+      if (json_skip_key(&je))
+        goto err_return;
+
       break;
 
     case JST_OBJ_END:
-      *value_type= (enum json_value_types) 0;
-      *value_start= (const char *) (je.s.c_str - je.sav_c_len);
+      *value= (const char *) (je.s.c_str - je.sav_c_len);
       *value_len= n_keys;
-      return 0;
+      return JSV_NOTHING;
     }
   }
 
 err_return:
-  return 1;
+  return JSV_BAD_JSON;
 }
 
+
+enum json_types json_get_object_nkey(const char *js,const char *js_end, int nkey,
+                       const char **keyname, const char **keyname_end,
+                       const char **value, int *value_len)
+{
+  return JSV_NOTHING;
+}
+
+
 /** Check if json is valid (well-formed)
 
   @retval 0 - success, json is well-formed
diff --git a/unittest/strings/CMakeLists.txt b/unittest/strings/CMakeLists.txt
index 2457475..0896e13 100644
--- a/unittest/strings/CMakeLists.txt
+++ b/unittest/strings/CMakeLists.txt
@@ -1,3 +1,3 @@
 
-MY_ADD_TESTS(strings LINK_LIBRARIES strings mysys)
+MY_ADD_TESTS(strings json LINK_LIBRARIES strings mysys)
 


More information about the commits mailing list