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
Loading