[augeas-devel] [PATCH] Fix segfault in get.c with L_MAYBE lens (bug#180)

Francis Giraldeau francis.giraldeau at gmail.com
Thu Feb 10 05:03:12 UTC 2011


When a L_MAYBE lens was the last child of a L_CONCAT inside a L_SUBTREE, then
the match in visit_exit top_frame(rec_state)->lens == lens->child was true,
causing combine of a frame when it shouldn't. This test is true because there
is no other lens following in the concat in this special case, hence the top
frame matched the child of the L_MAYBE.

To avoid this special case, we propose to push L_MAYBE lens on the frames
stack. If L_MAYBE is encountered in visit_exit, we pop at least one frame and
two if the child match. This way, the stack is always valid.

Closes trac ticket #180.
---
 src/get.c                               |    6 ++++--
 tests/modules/pass_simple_recursion.aug |   13 +++++++++++++
 2 files changed, 17 insertions(+), 2 deletions(-)

diff --git a/src/get.c b/src/get.c
index dbab6fa..9c58ac8 100644
--- a/src/get.c
+++ b/src/get.c
@@ -857,6 +857,8 @@ static void visit_enter(struct lens *lens,
         f->value = state->value;
         state->key = NULL;
         state->value = NULL;
+    } else if (lens->tag == L_MAYBE) {
+        push_frame(rec_state, lens);
     }
 }
 
@@ -996,10 +998,10 @@ static void visit_exit(struct lens *lens,
         else
             parse_combine(rec_state, lens, n);
     } else if (lens->tag == L_MAYBE) {
-        uint n = 0;
+        uint n = 1;
         if (rec_state->fused > 0
             && top_frame(rec_state)->lens == lens->child) {
-            n = 1;
+            n = 2;
         }
         if (rec_state->mode == M_GET)
             get_combine(rec_state, lens, n);
diff --git a/tests/modules/pass_simple_recursion.aug b/tests/modules/pass_simple_recursion.aug
index 2f69ae6..664ed3e 100644
--- a/tests/modules/pass_simple_recursion.aug
+++ b/tests/modules/pass_simple_recursion.aug
@@ -67,6 +67,19 @@ test unamb2 get "x" = { "x" }
 let rec maybe = [ del "a" "a" . maybe . del "b" "b" ]?
 test maybe get "aabb" = { { } }
 
+(* Test proper handling of '?'; bug #180 *)
+let rec maybe2 = [ del "a" "a" . maybe2 ]?
+test maybe2 get "aa" = { { } }
+
+let rec maybe3 = [ maybe3 . del "a" "a" ]?
+test maybe3 get "aa" = { { } }
+
+let rec maybe4 = [ del "a" "a" ] . maybe4?
+test maybe4 get "aa" = { } { }
+
+let rec maybe5 = maybe5? . [ del "a" "a" ]
+test maybe5 get "aa" = { } { }
+
 (* Test that parses ending with a SCAN are accepted; bug #126 *)
 let dels (s:string) = del s s
 let d2 = del /b*/ ""
-- 
1.7.1




More information about the augeas-devel mailing list