Merge branch 'release'
authorDavid Bremner <david@tethera.net>
Thu, 23 Feb 2017 13:08:15 +0000 (09:08 -0400)
committerDavid Bremner <david@tethera.net>
Thu, 23 Feb 2017 13:08:15 +0000 (09:08 -0400)
Merge in g_hash_table read-after-free fix

1  2 
lib/database.cc

diff --combined lib/database.cc
index 8016c4df3d167c2c6fd30dbbe5e3ba66dd3fbffc,eddb780c69ebc76ab8870fb93dfb23d01e1a6176..386dcd17adc4d0a91ab5eb10479907b254d32187
@@@ -42,7 -42,6 +42,7 @@@ using namespace std
  typedef struct {
      const char *name;
      const char *prefix;
 +    notmuch_field_flag_t flags;
  } prefix_t;
  
  #define NOTMUCH_DATABASE_VERSION 3
   * nearly universal to all mail messages).
   */
  
 -static prefix_t BOOLEAN_PREFIX_INTERNAL[] = {
 -    { "type",                 "T" },
 -    { "reference",            "XREFERENCE" },
 -    { "replyto",              "XREPLYTO" },
 -    { "directory",            "XDIRECTORY" },
 -    { "file-direntry",                "XFDIRENTRY" },
 -    { "directory-direntry",   "XDDIRENTRY" },
 -};
 -
 -static prefix_t BOOLEAN_PREFIX_EXTERNAL[] = {
 -    { "thread",                       "G" },
 -    { "tag",                  "K" },
 -    { "is",                   "K" },
 -    { "id",                   "Q" },
 -    { "path",                 "P" },
 -    { "property",             "XPROPERTY" },
 +static const
 +prefix_t prefix_table[] = {
 +    /* name                   term prefix     flags */
 +    { "type",                 "T",            NOTMUCH_FIELD_NO_FLAGS },
 +    { "reference",            "XREFERENCE",   NOTMUCH_FIELD_NO_FLAGS },
 +    { "replyto",              "XREPLYTO",     NOTMUCH_FIELD_NO_FLAGS },
 +    { "directory",            "XDIRECTORY",   NOTMUCH_FIELD_NO_FLAGS },
 +    { "file-direntry",                "XFDIRENTRY",   NOTMUCH_FIELD_NO_FLAGS },
 +    { "directory-direntry",   "XDDIRENTRY",   NOTMUCH_FIELD_NO_FLAGS },
 +    { "thread",                       "G",            NOTMUCH_FIELD_EXTERNAL },
 +    { "tag",                  "K",            NOTMUCH_FIELD_EXTERNAL },
 +    { "is",                   "K",            NOTMUCH_FIELD_EXTERNAL },
 +    { "id",                   "Q",            NOTMUCH_FIELD_EXTERNAL },
 +    { "path",                 "P",            NOTMUCH_FIELD_EXTERNAL },
 +    { "property",             "XPROPERTY",    NOTMUCH_FIELD_EXTERNAL },
      /*
       * Unconditionally add ':' to reduce potential ambiguity with
       * overlapping prefixes and/or terms that start with capital
       * letters. See Xapian document termprefixes.html for related
       * discussion.
       */
 -    { "folder",                       "XFOLDER:" },
 -};
 -
 -static prefix_t PROBABILISTIC_PREFIX[]= {
 -    { "from",                 "XFROM" },
 -    { "to",                   "XTO" },
 -    { "attachment",           "XATTACHMENT" },
 -    { "mimetype",             "XMIMETYPE"},
 -    { "subject",              "XSUBJECT"},
 +    { "folder",                       "XFOLDER:",     NOTMUCH_FIELD_EXTERNAL },
 +    { "from",                 "XFROM",        NOTMUCH_FIELD_EXTERNAL |
 +                                              NOTMUCH_FIELD_PROBABILISTIC },
 +    { "to",                   "XTO",          NOTMUCH_FIELD_EXTERNAL |
 +                                              NOTMUCH_FIELD_PROBABILISTIC },
 +    { "attachment",           "XATTACHMENT",  NOTMUCH_FIELD_EXTERNAL |
 +                                              NOTMUCH_FIELD_PROBABILISTIC },
 +    { "mimetype",             "XMIMETYPE",    NOTMUCH_FIELD_EXTERNAL |
 +                                              NOTMUCH_FIELD_PROBABILISTIC },
 +    { "subject",              "XSUBJECT",     NOTMUCH_FIELD_EXTERNAL |
 +                                              NOTMUCH_FIELD_PROBABILISTIC },
  };
  
  const char *
@@@ -287,9 -285,19 +287,9 @@@ _find_prefix (const char *name
  {
      unsigned int i;
  
 -    for (i = 0; i < ARRAY_SIZE (BOOLEAN_PREFIX_INTERNAL); i++) {
 -      if (strcmp (name, BOOLEAN_PREFIX_INTERNAL[i].name) == 0)
 -          return BOOLEAN_PREFIX_INTERNAL[i].prefix;
 -    }
 -
 -    for (i = 0; i < ARRAY_SIZE (BOOLEAN_PREFIX_EXTERNAL); i++) {
 -      if (strcmp (name, BOOLEAN_PREFIX_EXTERNAL[i].name) == 0)
 -          return BOOLEAN_PREFIX_EXTERNAL[i].prefix;
 -    }
 -
 -    for (i = 0; i < ARRAY_SIZE (PROBABILISTIC_PREFIX); i++) {
 -      if (strcmp (name, PROBABILISTIC_PREFIX[i].name) == 0)
 -          return PROBABILISTIC_PREFIX[i].prefix;
 +    for (i = 0; i < ARRAY_SIZE (prefix_table); i++) {
 +      if (strcmp (name, prefix_table[i].name) == 0)
 +          return prefix_table[i].prefix;
      }
  
      INTERNAL_ERROR ("No prefix exists for '%s'\n", name);
@@@ -644,7 -652,7 +644,7 @@@ parse_references (void *ctx
        ref = _parse_message_id (ctx, refs, &refs);
  
        if (ref && strcmp (ref, message_id)) {
-           g_hash_table_insert (hash, ref, NULL);
+           g_hash_table_add (hash, ref);
            last_ref = ref;
        }
      }
       * reference to the database.  We should avoid making a message
       * its own parent, thus the above check.
       */
-     return last_ref;
+     return talloc_strdup(ctx, last_ref);
  }
  
  notmuch_status_t
@@@ -1030,14 -1038,10 +1030,14 @@@ notmuch_database_open_verbose (const ch
  #if HAVE_XAPIAN_FIELD_PROCESSOR
        /* This currently relies on the query parser to pass anything
         * with a .. to the range processor */
 -      notmuch->date_field_processor = new DateFieldProcessor();
 -      notmuch->query_parser->add_boolean_prefix("date", notmuch->date_field_processor);
 -      notmuch->query_field_processor = new QueryFieldProcessor (*notmuch->query_parser, notmuch);
 -      notmuch->query_parser->add_boolean_prefix("query", notmuch->query_field_processor);
 +      {
 +          Xapian::FieldProcessor * date_fp = new DateFieldProcessor();
 +          Xapian::FieldProcessor * query_fp =
 +              new QueryFieldProcessor (*notmuch->query_parser, notmuch);
 +
 +          notmuch->query_parser->add_boolean_prefix("date", date_fp->release ());
 +          notmuch->query_parser->add_boolean_prefix("query", query_fp->release ());
 +      }
  #endif
        notmuch->last_mod_range_processor = new Xapian::NumberValueRangeProcessor (NOTMUCH_VALUE_LAST_MOD, "lastmod:");
  
        notmuch->query_parser->add_valuerangeprocessor (notmuch->date_range_processor);
        notmuch->query_parser->add_valuerangeprocessor (notmuch->last_mod_range_processor);
  
 -      for (i = 0; i < ARRAY_SIZE (BOOLEAN_PREFIX_EXTERNAL); i++) {
 -          prefix_t *prefix = &BOOLEAN_PREFIX_EXTERNAL[i];
 -          notmuch->query_parser->add_boolean_prefix (prefix->name,
 -                                                     prefix->prefix);
 -      }
 -
 -      for (i = 0; i < ARRAY_SIZE (PROBABILISTIC_PREFIX); i++) {
 -          prefix_t *prefix = &PROBABILISTIC_PREFIX[i];
 -          notmuch->query_parser->add_prefix (prefix->name, prefix->prefix);
 +      for (i = 0; i < ARRAY_SIZE (prefix_table); i++) {
 +          const prefix_t *prefix = &prefix_table[i];
 +          if (prefix->flags & NOTMUCH_FIELD_EXTERNAL) {
 +              if (prefix->flags & NOTMUCH_FIELD_PROBABILISTIC) {
 +                  notmuch->query_parser->add_prefix (prefix->name, prefix->prefix);
 +              } else {
 +                  notmuch->query_parser->add_boolean_prefix (prefix->name,
 +                                                             prefix->prefix);
 +              }
 +          }
        }
      } catch (const Xapian::Error &error) {
        IGNORE_RESULT (asprintf (&message, "A Xapian exception occurred opening database: %s\n",
@@@ -1130,6 -1133,13 +1130,6 @@@ notmuch_database_close (notmuch_databas
      delete notmuch->last_mod_range_processor;
      notmuch->last_mod_range_processor = NULL;
  
 -#if HAVE_XAPIAN_FIELD_PROCESSOR
 -    delete notmuch->date_field_processor;
 -    notmuch->date_field_processor = NULL;
 -    delete notmuch->query_field_processor;
 -    notmuch->query_field_processor = NULL;
 -#endif
 -
      return status;
  }
  
@@@ -1701,7 -1711,7 +1701,7 @@@ notmuch_database_end_atomic (notmuch_da
         * However, we rely on flushing to test atomicity. */
        const char *thresh = getenv ("XAPIAN_FLUSH_THRESHOLD");
        if (thresh && atoi (thresh) == 1)
 -          db->flush ();
 +          db->commit ();
      } catch (const Xapian::Error &error) {
        _notmuch_database_log (notmuch, "A Xapian exception occurred committing transaction: %s.\n",
                 error.get_msg().c_str());