Skip to content
Snippets Groups Projects
  1. Nov 30, 2019
  2. Nov 29, 2019
  3. Nov 28, 2019
  4. Nov 27, 2019
  5. Nov 26, 2019
    • xentrac's avatar
      Fix bug #19 in permutations and sequences too · 032430e3
      xentrac authored
      In `h_sequence__ma` the same bug occurs, and it manifests as a crash
      in the same way, so I've added a test for it.  In `h_permutation__ma`
      it evidently exists in the same form, but I haven't figured out how to
      reproduce it; in that case I added a fix to the implementation, but no
      test.
      032430e3
    • xentrac's avatar
      Add regression test for bug #19 · 302f2f9f
      xentrac authored
      I committed the fix for bug #19 without a test because I didn't know
      how our test worked yet; here's a test.
      
      A somewhat more desirable way to do this would be to commit the
      test *first*, marked as "incomplete" with `g_test_incomplete()` (an
      expected failure).  However, `g_test_incomplete()` does not handle
      segfaults!  There's no way to mark a segfaulting test as an "expected
      segfault".  So if you want to verify that this test reveals the bug,
      you'll need to `git show thiscommit | patch -p1` or something, in a
      tree that doesn't have the fix applied.  Or you can comment out the
      fix, I guess.
      302f2f9f
  6. Nov 23, 2019
    • xentrac's avatar
      Fix #19, GLR backend reaches unreachable code · 9e662b68
      xentrac authored
      Original behavior:
      
          hammer/build/debug/src/bindings/python$ LD_LIBRARY_PATH=. gdb python
          ...
          (gdb) r
          ...
          Python 2.7.6 (default, Nov 12 2018, 20:00:40)
          [GCC 4.8.4] on linux2
          Type "help", "copyright", "credits" or "license" for more information.
          >>> if 1:
          ...     import hammer as h
          ...     h.choice(h.ch_range('0', '9'), h.ch_range('A', 'Z'), h.ch_range('a', 'z')).compile(h._PB_GLR)
          ...
      
          Program received signal SIGSEGV, Segmentation fault.
          0xb79ecab2 in collect_nts (grammar=0x836abe0, symbol=0xb7d550a4)
              at build/debug/src/cfgrammar.c:120
          120	      for(x = (*s)->items; *x != NULL; x++) {
          (gdb) bt
          #0  0xb79ecab2 in collect_nts (grammar=0x836abe0, symbol=0xb7d550a4)
              at build/debug/src/cfgrammar.c:120
          #1  0xb79ecacd in collect_nts (grammar=0x836abe0, symbol=0x836ab58)
              at build/debug/src/cfgrammar.c:121
          #2  0xb79ec90a in h_cfgrammar_ (mm__=0xb79ff4b4 <system_allocator>,
              desugared=0x836ab58) at build/debug/src/cfgrammar.c:66
          #3  0xb79e8207 in h_lalr_compile (mm__=0xb79ff4b4 <system_allocator>,
              parser=0x836ab40, params=0x0) at build/debug/src/backends/lalr.c:280
          #4  0xb79e634a in h_glr_compile (mm__=0xb79ff4b4 <system_allocator>,
              parser=0x836ab40, params=0x0) at build/debug/src/backends/glr.c:15
          #5  0xb79f0eef in h_compile__m (mm__=0xb79ff4b4 <system_allocator>,
              parser=0x836ab40, backend=PB_GLR, params=0x0)
              at build/debug/src/hammer.c:97
          #6  0xb79f0e9d in h_compile (parser=parser@entry=0x836ab40, backend=PB_GLR,
              params=params@entry=0x0) at build/debug/src/hammer.c:92
          #7  0xb7a54ca4 in HParser__compile (backend=<optimized out>, self=0x836ab40)
              at hammer_wrap.c:3567
      
      New behavior:
      
          hammer/build/debug/src/bindings/python$ LD_LIBRARY_PATH=. gdb python
          ...
          (gdb) r
          ...
          Python 2.7.6 (default, Nov 12 2018, 20:00:40)
          [GCC 4.8.4] on linux2
          Type "help", "copyright", "credits" or "license" for more information.
          >>> if 1:
          ...     import hammer as h
          ...     h.choice(h.ch_range('0', '9'), h.ch_range('A', 'Z'), h.ch_range('a', 'z')).compile(h._PB_GLR)
          ...
          True
          >>> ^D
          [Inferior 1 (process 19621) exited normally]
          (gdb) quit
      
      After thrashing about for a few hours, this was the crucial clue:
      
          >>> import hammer as h
          >>> h.choice(h.ch('0')).compile(h._PB_GLR)
          ==18856== Conditional jump or move depends on uninitialised value(s)
          ==18856==    at 0x4A34FE9: h_desugar (desugar.c:7)
          ==18856==    by 0x4A2D150: h_desugar_augmented (lalr.c:261)
          ==18856==    by 0x4A2D1F7: h_lalr_compile (lalr.c:280)
          ==18856==    by 0x4A2B349: h_glr_compile (glr.c:15)
          ==18856==    by 0x4A35EEE: h_compile__m (hammer.c:97)
          ==18856==    by 0x4A35E9C: h_compile (hammer.c:92)
          ==18856==    by 0x49B0CA3: HParser__compile (hammer_wrap.c:3567)
      
      The particular thing that it's saying is uninitialized seems to be
      
            if(parser->desugared == NULL) {
      
      The `parser` in question is the `HParser` we're trying to desugar,
      which is presumably the choice object created by `h.choice`, which
      seems to be invoking `h_choice__a`:
      
          def choice(*args): return _h_choice__a(list(args))
      
      That was implemented as follows:
      
          HParser* h_choice__a(void *args[]) {
            return h_choice__ma(&system_allocator, args);
          }
      
          HParser* h_choice__ma(HAllocator* mm__, void *args[]) {
            size_t len = -1; // because do...while
            const HParser *arg;
      
            do {
              arg=((HParser **)args)[++len];
            } while(arg);
      
            HSequence *s = h_new(HSequence, 1);
            s->p_array = h_new(HParser *, len);
      
            for (size_t i = 0; i < len; i++) {
              s->p_array[i] = ((HParser **)args)[i];
            }
      
            s->len = len;
            HParser *ret = h_new(HParser, 1);
            ret->vtable = &choice_vt;
            ret->env = (void*)s;
            ret->backend = PB_MIN;
            return ret;
          }
      
      Indeed it does not seem to have been initializing `desugared`.  Fixing
      this cures this symptom.
      
      Other things it's probably worth checking out:
      
      - Are there other places where we create HParser objects where one or
        more fields may be uninitialized?
      - Perhaps `h_new` should zero the memory it returns, since it's only
        used for fixed-size objects and not things like variable-size
        character buffers?
      9e662b68
  7. Nov 20, 2019
  8. Nov 08, 2019
    • Andrea Shepard's avatar
      Merge branch 'master' into 'master' · eebdb1be
      Andrea Shepard authored
      various minor cleanups
      
      See merge request hammer/hammer!6
      eebdb1be
    • xentrac's avatar
      Clean up man page slightly · 3055470c
      xentrac authored
      3055470c
    • xentrac's avatar
      Clean up apparent intended Markdown in HACKING · cf054521
      xentrac authored
      Also remove a couple of spelling and capitalization nits.  I did this
      because I was reading the document and they bothered me.
      cf054521
    • xentrac's avatar
      Fix noise memory leaks in other base64 examples · 4cf306ce
      xentrac authored
      It bothers me a little bit that I can't figure out how to free the
      parser --- surely that is a thing that the bindings for other
      languages need to do --- but storing a pointer to the parser in a
      statically-allocated variable, as in base64.c, at least stops valgrind
      from reporting the parser as a memory leak.
      4cf306ce
    • xentrac's avatar
      Fix noise memory leak in examples/base64.c · 235f6f74
      xentrac authored
      Obviously we don't care if examples/base64.c leaks memory before
      exiting, but things like that are noise that make it hard to tell if
      there's a real memory-leak problem somewhere else; it also sets a bad
      example for code that someone might write modeled on the example.
      This patch ensures that the example frees its allocations as it
      should.
      235f6f74
  9. Oct 25, 2019
  10. Oct 09, 2019
Loading