[Senna-dev 479] Re: snippet関数を使うとクラッシュする

Back to archive index

Tasuku SUENAGA a****@razil*****
2007年 2月 25日 (日) 13:23:40 JST


末永です。

立松 聖久 wrote:
> 立松です.
>
> Senna-dev 426あたりから引きずっている問題なんですが,以下のクエリを投げ
> るとMySQLがクラッシュします.
> snippet関数がなければ正常に動作します.
> (後略)

上記の問題、調査いたします。
昔のバージョン相当に挙動を戻すパッチを作成しました。
このパッチをお試しください。

--- udf_snippet.c	2007-02-25 13:12:58.000000000 +0900
+++ udf_snippet_new.c	2007-02-25 13:18:29.000000000 +0900
@@ -73,8 +73,10 @@
 {
   char *result;
   char *buffer;
+  char *source;
   size_t result_len;
   size_t buffer_len;
+  size_t source_len;
   char *keytags;
   sen_snip *snip;
 } snip_struct;
@@ -87,42 +89,31 @@
   sen_encoding enc;
   sen_snip *snip;
   sen_snip_mapping *map;
-  unsigned int i;
+  int i, keytagslength;
   long long slength, snumber, htmlflag;
-  const enum Item_result arg_types[] =
-    {STRING_RESULT, INT_RESULT, INT_RESULT, STRING_RESULT, INT_RESULT,
STRING_RESULT, STRING_RESULT};
+  char *keytags, *p, *q, *r;

   initid->ptr = NULL;

-  if (args->arg_count < 10) {
-    strcpy(message, "snippet function requires at least 10 parameters.");
-    return 1;
-  }
-  if ((args->arg_count % 3) != 1) {
-    strcpy(message, "number of parameters for snippet function is wrong.");
+  if (args->arg_count < 10
+      || (args->arg_count % 3) != 1
+      || args->arg_type[1] != INT_RESULT
+      || args->args[1] == NULL
+      || args->arg_type[2] != INT_RESULT
+      || args->args[2] == NULL
+      || args->arg_type[3] != STRING_RESULT
+      || args->args[3] == NULL
+      || args->lengths[3] > INT_MAX
+      || args->arg_type[4] != INT_RESULT
+      || args->args[4] == NULL
+      || args->arg_type[5] != STRING_RESULT
+      || args->args[5] == NULL
+      || args->lengths[5] > INT_MAX
+      || args->arg_type[6] != STRING_RESULT
+      || args->args[6] == NULL || args->lengths[6] > INT_MAX) {
+    strcpy(message, "invalid parameters");
     return 1;
   }
-  for (i = 1; i <= 6; i++) {
-    if (!args->args[i]) {
-      sprintf(message, "parameter number %d is NULL!", i + 1);
-      return 1;
-    }
-    if (args->arg_type[i] != arg_types[i]) {
-      sprintf(message, "type of parameter number %d is wrong.", i + 1);
-      return 1;
-    }
-    if (arg_types[i] == STRING_RESULT && args->lengths[i] > INT_MAX) {
-      sprintf(message, "parameter number %d is too long!", i + 1);
-      return 1;
-    }
-  }
-
-  for (i = 7; i < args->arg_count; i++) {
-    if (args->arg_type[i] != STRING_RESULT) {
-      sprintf(message, "parameter number %d is invalid!", i + 1);
-      return 1;
-    }
-  }

   slength = *((long long *) args->args[1]);
   snumber = *((long long *) args->args[2]);
@@ -160,6 +151,44 @@
     map = (sen_snip_mapping *) -1;
   }

+  keytagslength = 0;
+  for (i = 7; i < args->arg_count; i++) {
+    if (args->arg_type[i] != STRING_RESULT) {
+      sprintf(message, "invalid parameters(%dth)", i);
+      return 1;
+    }
+    if (args->lengths[i] >= INT_MAX) {
+      sprintf(message, "too long parameters(%dth)", i);
+      return 1;
+    }
+    keytagslength += args->lengths[i] + 1;
+  }
+
+  if (!(keytags = (char *) malloc(sizeof(char) * keytagslength))) {
+    strcpy(message, "memory allocation error !(tags)");
+    return 1;
+  }
+
+  p = keytags;
+  snip = sen_snip_open(enc, SEN_SNIP_NORMALIZE, slength, snumber, "",
0, "", 0, map);
+  for (i = 7; i < args->arg_count; i += 3) {
+
+    memcpy(p, args->args[i], args->lengths[i]); /* keyword copy */
+    p[args->lengths[i]] = '\0';
+    q = p + args->lengths[i] + 1;
+    memcpy(q, args->args[i + 1], args->lengths[i + 1]); /* opentag copy */
+    q[args->lengths[i + 1]] = '\0';
+    r = q + args->lengths[i + 1] + 1;
+    memcpy(r, args->args[i + 2], args->lengths[i + 2]); /* closetag copy */
+    r[args->lengths[i + 2]] = '\0';
+
+    if (sen_snip_add_cond(snip, p, strlen(p), q, strlen(q), r,
strlen(r)) != sen_success) {
+      strcpy(message, "cannot add conditions");
+      return 1;
+    }
+    p = r + args->lengths[i + 2] + 1;
+  }
+
   if (!(ptr = (snip_struct *) malloc(sizeof(snip_struct)))) {
     strcpy(message, "memory allocation error !(snip_struct)");
     return 1;
@@ -170,8 +199,8 @@
   initid->max_length = 65535;   /* represents blob */
   initid->maybe_null = FALSE;

-  ptr->snip = sen_snip_open
-    (enc, SEN_SNIP_NORMALIZE, slength, snumber, "", 0, "", 0, map);
+  ptr->snip = snip;
+  ptr->keytags = keytags;
   ptr->result_len = (size_t) ((long double) slength * snumber * 1.3);
   if (ptr->result_len < MINIMUM_RESULT_LENGTH) {
     ptr->result_len = MINIMUM_RESULT_LENGTH;
@@ -184,6 +213,8 @@
     return 1;
   }

+  ptr->source_len = 0;
+
   if (!(ptr->result = (char *) malloc(sizeof(char) * ptr->result_len))) {
     snippet_deinit(initid);
     strcpy(message, "memory allocation error !(result)");
@@ -196,6 +227,13 @@
     return 1;
   }

+  /* zero length allocation */
+  if (!(ptr->source = (char *) malloc(sizeof(char) * ptr->source_len))) {
+    snippet_deinit(initid);
+    strcpy(message, "memory allocation error !(source)");
+    return 1;
+  }
+
   return 0;
 }

@@ -215,6 +253,9 @@
     if (ptr->buffer) {
       free(ptr->buffer);
     }
+    if (ptr->source) {
+      free(ptr->source);
+    }
     if (ptr->keytags) {
       free(ptr->keytags);
     }
@@ -228,60 +269,41 @@
 {
   snip_struct *ptr;
   sen_snip *snip;
-  unsigned int i, n_results, estimated_length, max_tagged_len;
-  char *p;
+  int i;
+  unsigned int n_results, estimated_length, max_tagged_len;
+  char *p, *q;

   ptr = (snip_struct *) initid->ptr;
   snip = ptr->snip;

-  if (!ptr->keytags){
-    unsigned int keytagslength;
-    char *q, *r;
-
-    keytagslength = 0;
-    for (i = 7; i < args->arg_count; i++) {
-      if (args->lengths[i] >= INT_MAX) {
-        sprintf(ptr->result, "parameter number %d is too long!", i + 1);
-        goto exit;
-      }
-      keytagslength += args->lengths[i];
-    }
-
-    if (!(ptr->keytags = (char *) malloc(sizeof(char) * keytagslength))) {
-      sprintf(ptr->result, "memory allocation error !(tags)");
-      goto exit;
-    }
-
-    p = ptr->keytags;
-    for (i = 7; i < args->arg_count; i += 3) {
-
-      memcpy(p, args->args[i], args->lengths[i]); /* keyword copy */
-      q = p + args->lengths[i];
-      memcpy(q, args->args[i + 1], args->lengths[i + 1]); /* opentag
copy */
-      r = q + args->lengths[i + 1];
-      memcpy(r, args->args[i + 2], args->lengths[i + 2]); /* closetag
copy */
-
-      if (sen_snip_add_cond(snip, p, args->lengths[i],
-                            q, args->lengths[i + 1],
-                            r, args->lengths[i + 2]) != sen_success) {
-        strcpy(ptr->result, "cannot add conditions");
-        goto exit;
-      }
-      p = r + args->lengths[i + 2];
-    }
-  }
-
+  p = ptr->result;
   if (args->arg_type[0] != STRING_RESULT) {
     strcpy(ptr->result, "cannot make snippet");
     goto exit;
-  }
-  if (args->lengths[0] >= INT_MAX) {
+  } else if (args->lengths[0] >= INT_MAX) {
     strcpy(ptr->result, "string is too long");
     goto exit;
-  }
-  if (args->args[0]) {
-    if (sen_snip_exec(snip, args->args[0], args->lengths[0],
&n_results, &max_tagged_len)
-        != sen_success) {
+  } else if (args->args[0]) {
+
+    if ((args->args[0])[args->lengths[0]] == '\0') {
+      q = args->args[0];        /* null terminated */
+    } else {                    /* not null terminated */
+      /* source realloc */
+      if (ptr->source_len <= args->lengths[0]) {
+        ptr->source =
+          (char *) realloc(ptr->source, sizeof(char) *
(args->lengths[0] + 1));
+        if (!ptr->result) {
+          strcpy(ptr->result, "cannot reallocate memory for source");
+          goto exit;
+        }
+        ptr->source_len = args->lengths[0] + 1;
+      }
+      q = ptr->source;
+      memcpy(q, args->args[0], args->lengths[0]);
+      q[args->lengths[0]] = '\0';
+    }
+
+    if (sen_snip_exec(snip, q, strlen(q), &n_results, &max_tagged_len)
!= sen_success) {
       strcpy(ptr->result, "cannot make snippet");
       goto exit;
     }
@@ -310,26 +332,23 @@

     p = ptr->result;
     for (i = 0; i < n_results; i++) {
-      unsigned int r_len;
-      if (sen_snip_get_result(snip, i, ptr->buffer, &r_len) !=
sen_success) {
+      if (sen_snip_get_result(snip, i, ptr->buffer, NULL) != sen_success) {
         strcpy(ptr->result, "cannot get result");
         goto exit;
       }
       memcpy(p, args->args[5], args->lengths[5]);
       p += args->lengths[5];
-      memcpy(p, ptr->buffer, r_len);
-      p += r_len;
+      for (q = ptr->buffer; *q != '\0'; *p++ = *q++) {
+      }
       memcpy(p, args->args[6], args->lengths[6]);
       p += args->lengths[6];
     }
-    *length = (size_t)(p - ptr->result);
   }
-  else {
-    *length = 0;
-  }
-  return ptr->result;
+
 exit:
+  *p = '\0';
   *length = strlen(ptr->result);
+
   return ptr->result;
 }

---
Tasuku SUENAGA <a****@razil*****>



Senna-dev メーリングリストの案内
Back to archive index