Browse Source

Test and fix leaks in graph_iter_next().

Stefano Cossu 1 year ago
parent
commit
c98dd9fe61
4 changed files with 36 additions and 27 deletions
  1. 4 3
      include/graph.h
  2. 6 11
      src/codec/codec_nt.c
  3. 14 13
      src/graph.c
  4. 12 0
      test/test_graph.c

+ 4 - 3
include/graph.h

@@ -293,14 +293,15 @@ LSUP_graph_lookup (const LSUP_Graph *gr, const LSUP_Term *s,
  *
  * @param it[in] Iterator handle obtained through #LSUP_graph_lookup.
  *
- * @param spo[out] Triple to be populated with the next result. May be NULL
- *  (e.g. for counters).
+ * @param spo[out] Triple handle pointer to be populated with the next result.
+ * If not NULL, it will allocate a new triple and new terms, and should be
+ * freed with LSUP_triple_free().
  *
  * @return LSUP_OK if a result was found; LSUP_END if the end of the match list
  *  was reached.
  */
 LSUP_rc
-LSUP_graph_iter_next (LSUP_GraphIterator *it, LSUP_Triple *spo);
+LSUP_graph_iter_next (LSUP_GraphIterator *it, LSUP_Triple **spo);
 
 
 /** @brief Return the graph related to an iterator.

+ 6 - 11
src/codec/codec_nt.c

@@ -4,7 +4,6 @@
 /// NT codec iterator type.
 typedef struct {
     const LSUP_Codec *  codec;      // Codec that generated this iterator.
-    LSUP_Triple *       trp;        // RDF fragment being encoded.
     LSUP_GraphIterator *gr_it;      // Graph iterator.
     const LSUP_NSMap *  nsm;        // Namespace map.
     size_t              cur;        // Internal cursor.
@@ -120,7 +119,6 @@ gr_to_nt_init (const LSUP_Graph *gr)
     it->codec = &nt_codec;
     it->gr_it = LSUP_graph_lookup(gr, NULL, NULL, NULL, &it->cur);
     it->nsm = LSUP_graph_namespace (gr);
-    it->trp = TRP_DUMMY;
 
     return it;
 }
@@ -129,12 +127,14 @@ gr_to_nt_init (const LSUP_Graph *gr)
 static LSUP_rc
 gr_to_nt_iter (void *h, char **res) {
     LSUP_NTCodecIterator *it = h;
-    LSUP_rc rc = LSUP_graph_iter_next (it->gr_it, it->trp);
+    LSUP_Triple *spo = NULL;
+    LSUP_rc rc = LSUP_graph_iter_next (it->gr_it, &spo);
     if (rc != LSUP_OK) goto finally;
 
-    term_to_nt (it->trp->s, it->nsm, &it->str_s);
-    term_to_nt (it->trp->p, it->nsm, &it->str_p);
-    term_to_nt (it->trp->o, it->nsm, &it->str_o);
+    term_to_nt (spo->s, it->nsm, &it->str_s);
+    term_to_nt (spo->p, it->nsm, &it->str_p);
+    term_to_nt (spo->o, it->nsm, &it->str_o);
+    LSUP_triple_free (spo);
 
     // 3 term separators + dot + newline + terminal = 6
     char *tmp = realloc (
@@ -152,10 +152,6 @@ gr_to_nt_iter (void *h, char **res) {
     it->cur++;
 
 finally:
-    LSUP_term_free (it->trp->s); it->trp->s = NULL;
-    LSUP_term_free (it->trp->p); it->trp->p = NULL;
-    LSUP_term_free (it->trp->o); it->trp->o = NULL;
-
     return rc;
 }
 
@@ -165,7 +161,6 @@ gr_to_nt_done (void *h)
 {
     LSUP_NTCodecIterator *it = h;
     LSUP_graph_iter_free (it->gr_it);
-    LSUP_triple_free (it->trp);
     free (it->str_s);
     free (it->str_p);
     free (it->str_o);

+ 14 - 13
src/graph.c

@@ -366,12 +366,11 @@ LSUP_graph_copy_contents (const LSUP_Graph *src, LSUP_Graph *dest)
 
     LSUP_GraphIterator *it = LSUP_graph_lookup (src, NULL, NULL, NULL, NULL);
 
-    LSUP_Triple spo;
-
+    LSUP_Triple *spo = NULL;
     LSUP_GraphIterator *add_it = LSUP_graph_add_init (dest);
     while (LSUP_graph_iter_next (it, &spo) != LSUP_END) {
-        LSUP_rc add_rc = LSUP_graph_add_iter (add_it, &spo);
-        LSUP_triple_done (&spo);
+        LSUP_rc add_rc = LSUP_graph_add_iter (add_it, spo);
+        LSUP_triple_free (spo);
         if (LIKELY (add_rc == LSUP_OK)) rc = LSUP_OK;
         else if (add_rc < 0) {
             rc = add_rc;
@@ -421,18 +420,20 @@ LSUP_graph_lookup (
 
 
 LSUP_rc
-LSUP_graph_iter_next (LSUP_GraphIterator *it, LSUP_Triple *spo)
+LSUP_graph_iter_next (LSUP_GraphIterator *it, LSUP_Triple **spo_p)
 {
     LSUP_rc rc = graph_iter_next_buffer (it);
     PRCCK (rc);
     if (rc != LSUP_OK) return rc;
 
-    spo->s = LSUP_term_new_from_buffer (it->sspo->s);
-    if (!spo->s) return LSUP_ERROR;
-    spo->p = LSUP_term_new_from_buffer (it->sspo->p);
-    if (!spo->p) return LSUP_ERROR;
-    spo->o = LSUP_term_new_from_buffer (it->sspo->o);
-    if (!spo->o) return LSUP_ERROR;
+    LSUP_Triple *spo = LSUP_triple_new (
+        LSUP_term_new_from_buffer (it->sspo->s),
+        LSUP_term_new_from_buffer (it->sspo->p),
+        LSUP_term_new_from_buffer (it->sspo->o)
+    );
+    if (UNLIKELY (!spo)) return LSUP_MEM_ERR;
+
+    *spo_p = spo;
 
     return LSUP_OK;
 }
@@ -466,8 +467,8 @@ LSUP_graph_contains (const LSUP_Graph *gr, const LSUP_Triple *spo)
 {
     LSUP_GraphIterator *it = LSUP_graph_lookup (
             gr, spo->s, spo->p, spo->o, NULL);
-    LSUP_Triple *tmp_spo = TRP_DUMMY;
-    bool rc = LSUP_graph_iter_next (it, tmp_spo) != LSUP_END;
+    LSUP_Triple *tmp_spo = NULL;
+    bool rc = LSUP_graph_iter_next (it, &tmp_spo) != LSUP_END;
 
     LSUP_triple_free (tmp_spo);
     LSUP_graph_iter_free (it);

+ 12 - 0
test/test_graph.c

@@ -136,6 +136,18 @@ _graph_lookup (LSUP_StoreType type)
                 gr, lu_trp[i][0], lu_trp[i][1], lu_trp[i][2], &ct);
         EXPECT_INT_EQ (ct, lu_ct[i]);
 
+        // Verify that iteration count matches stat count.
+        LSUP_Triple *spo = NULL;
+        ct = 0;
+        while (LSUP_graph_iter_next (it, &spo) != LSUP_END) {
+            ct++;
+            // TODO do something useful with the triple.
+            LSUP_triple_free (spo);
+            spo = NULL;
+        }
+        LSUP_triple_free (spo);
+        EXPECT_INT_EQ (ct, lu_ct[i]);
+
         /* TODO
         for (int j = 0; j < 8; j++) {
             for (int k = 0; LSUP_graph_iter_next(it) != LSUP_END; k++) {