[Groonga-commit] groonga/groonga at a61dfbe [master] hash: add total key size overflow check

Back to archive index

Kouhei Sutou null+****@clear*****
Thu Jan 14 18:07:04 JST 2016


Kouhei Sutou	2016-01-14 18:07:04 +0900 (Thu, 14 Jan 2016)

  New Revision: a61dfbe6dd2b9e53d11cea4698ec8403e061b146
  https://github.com/groonga/groonga/commit/a61dfbe6dd2b9e53d11cea4698ec8403e061b146

  Message:
    hash: add total key size overflow check

  Modified files:
    lib/hash.c

  Modified: lib/hash.c (+32 -1)
===================================================================
--- lib/hash.c    2016-01-14 17:11:25 +0900 (2bb719e)
+++ lib/hash.c    2016-01-14 18:07:04 +0900 (fd5f96b)
@@ -1245,6 +1245,8 @@ grn_array_unblock(grn_ctx *ctx, grn_array *array)
 #define GRN_HASH_SEGMENT_SIZE 0x400000
 #define GRN_HASH_KEY_MAX_N_SEGMENTS 0x400
 #define W_OF_KEY_IN_A_SEGMENT 22
+#define GRN_HASH_KEY_MAX_TOTAL_SIZE\
+  ((1ULL << W_OF_KEY_IN_A_SEGMENT) * GRN_HASH_KEY_MAX_N_SEGMENTS - 1)
 #define IDX_MASK_IN_A_SEGMENT 0xfffff
 
 typedef struct {
@@ -1327,6 +1329,21 @@ enum {
   GRN_HASH_BITMAP_SEGMENT = 3
 };
 
+inline static int
+grn_hash_name(grn_ctx *ctx, grn_hash *hash, char *buffer, int buffer_size)
+{
+  int name_size;
+
+  if (DB_OBJ(hash)->id == GRN_ID_NIL) {
+    grn_strcpy(buffer, buffer_size, "(anonymous)");
+    name_size = strlen(buffer);
+  } else {
+    name_size = grn_obj_name(ctx, (grn_obj *)hash, buffer, buffer_size);
+  }
+
+  return name_size;
+}
+
 inline static grn_bool
 grn_hash_is_io_hash(grn_hash *hash)
 {
@@ -1459,6 +1476,19 @@ grn_io_hash_entry_put_key(grn_ctx *ctx, grn_hash *hash,
     if (key_size >= GRN_HASH_SEGMENT_SIZE) {
       return GRN_INVALID_ARGUMENT;
     }
+    if (key_size > (GRN_HASH_KEY_MAX_TOTAL_SIZE - header->curr_key)) {
+      char name[GRN_TABLE_MAX_KEY_SIZE];
+      int name_size;
+      name_size = grn_hash_name(ctx, hash, name, GRN_TABLE_MAX_KEY_SIZE);
+      ERR(GRN_NOT_ENOUGH_SPACE,
+          "[hash][key][put] total key size is over: <%.*s>: "
+          "max=%" GRN_FMT_INT64U ": current=%u: new key size=%u",
+          name_size, name,
+          GRN_HASH_KEY_MAX_TOTAL_SIZE,
+          header->curr_key,
+          key_size);
+      return ctx->rc;
+    }
     key_offset = header->curr_key;
     segment_id = (key_offset + key_size) >> W_OF_KEY_IN_A_SEGMENT;
     if ((key_offset >> W_OF_KEY_IN_A_SEGMENT) != segment_id) {
@@ -2206,7 +2236,8 @@ grn_io_hash_add(grn_ctx *ctx, grn_hash *hash, uint32_t hash_value,
   }
 
   if (grn_hash_entry_put_key(ctx, hash, entry, hash_value, key, key_size)) {
-    /* TODO: error handling. */
+    grn_hash_delete_by_id(ctx, hash, entry_id, NULL);
+    return GRN_ID_NIL;
   }
 
   if (value) {
-------------- next part --------------
HTML����������������������������...
Download 



More information about the Groonga-commit mailing list
Back to archive index