erlc bug: no_bs_match_state (OTP-R10B-10 / compiler-4.3.12)

Pascal Brisset pascal.brisset@REDACTED
Fri Apr 21 00:44:56 CEST 2006


Erlc crashes on the attached erlang module with this error:

 | bug_bin: function foo/1+13:
 |   Internal consistency check failed - please report this bug.
 |   Instruction: {bs_restore,0}
 |   Error:       no_bs_match_state:

This message comes from lib/compiler/src/beam_validator.erl,
which performs a kind of abstract interpretation on the beam code.
In particular, it keeps track of internal variables of the virtual
machine that are used for the implementation of pattern-matching
on binaries.  The validity of these variables is stored in
(Vst#vst.current)#st.bsm throughout the control flow analysis.

Looking at the generated beam code with erlc -S:

    10  {function, foo, 1, 2}.
    11    {label,1}.
    12      {func_info,{atom,bug_bin},{atom,foo},1}.
    13    {label,2}.
    14      {test,bs_start_match,{f,1},[{x,0}]}.
    15      {bs_save,0}.
    16      {test,bs_get_binary,
    17            {f,3},
    18            [{atom,all},8,{field_flags,[aligned,unsigned,big]},{x,1}]}.
    19      {test,bs_test_tail,{f,3},[0]}.
    20      {bs_init2,{f,3},0,0,2,{field_flags,[]},{x,2}}.
    21      {test,is_ne,{f,3},[{x,1},{x,2}]}.
    22      {move,{atom,ok},{x,0}}.
    23      return.
    24    {label,3}.
    25      {bs_restore,0}.
    26      {test,bs_test_tail,{f,1},[0]}.
    27      {move,{atom,ok},{x,0}}.
    28      return.

Lines 20-21 implement the guard Rest/=<<>>.  An empty binary is
created and compared to register X1, which contains Rest.

beam_validator considers bsm to be invalid after bs_init2,
presumably in accordance with this comment:
  %%% The bsm field is reset to 'undefined' by instructions that may cause a
  %%% a garbage collection (might move the binary) and/or context switch
  %%% (may invalidate the save points).
As a consequence, when beam_validator examines the control flow
from line 21 to line 25, it decides that bs_restore cannot execute
safely.

The problem also occurs whenever a guard allocates memory;
for example "foo(<<Rest/binary>>) when Rest/=[0]".

I'm not sure how this should be fixed.  The GC could scan the
pointers in erts_mb and erts_save_mb.  Or the allocator could
be prevented from relocating data while a binary match is in
progress.

Maybe earlier versions of erlc also generate "unsafe" code which
goes unnoticed because they don't have beam_validator.  Or maybe
there is no risk at all and the validator is too strict.

Credit for isolating this problem goes to Florent and Christophe
at Cellicium.

-- Pascal


-------------- next part --------------
An embedded and charset-unspecified text was scrubbed...
Name: bug_bin.erl
URL: <http://erlang.org/pipermail/erlang-bugs/attachments/20060421/7cc902ff/attachment.ksh>


More information about the erlang-bugs mailing list