Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cmm miscompile: cross-module inlining causes catch ID collision #7702

Closed
vicuna opened this issue Dec 30, 2017 · 7 comments
Closed

cmm miscompile: cross-module inlining causes catch ID collision #7702

vicuna opened this issue Dec 30, 2017 · 7 comments
Assignees

Comments

@vicuna
Copy link

vicuna commented Dec 30, 2017

Original bug ID: 7702
Reporter: chengsun
Assigned to: @gasche
Status: resolved (set by @gasche on 2018-01-11T10:33:51Z)
Resolution: fixed
Priority: normal
Severity: crash
Version: 4.06.0
Fixed in version: 4.07.0+dev/beta2/rc1/rc2
Category: back end (clambda to assembly)
Monitored by: chengsun @nojb @hhugo @gasche @yakobowski

Bug description

The attached code miscompiles (on 4.03.0 through trunk, no flambda) due to cross-module inlining.

The cmm generated for b.ml looks incorrect. As far as I can tell, an ID is generated for a catch lambda using next_raise_count, but this ID is already used in the clambda inlined from a.ml.

a.ml:

let _unused _ = try () with _ -> ()

let trigger_bug x =
let ok =
match x with
| None
| Some "" -> true
| Some _ -> false
in
if x = Some "" && not ok then
failwith "impossible"
[@@inline always]

b.ml:

let bug x = A.trigger_bug x

c.ml:

let () =
B.bug (Some "");
Printf.printf "Bug failed to trigger :(\n

Steps to reproduce

$ tar xzf bug.tar.gz
$ ./compile.sh
$ ./a.out
Fatal error: exception Failure("impossible")

File attachments

@vicuna
Copy link
Author

vicuna commented Dec 31, 2017

Comment author: @nojb

The 4.06 cmm for A.trigger_bug is

(function{a.ml:3,16-166} camlA__trigger_bug_1004 (x/1005: val)
(let
ok/1006
(catch
(if (!= x/1005 1)
(let switch/1210 (load_mut val x/1005)
(catch
(let size/1212 (>>u (load_mut int (+a switch/1210 -8)) 10)
(if (>= size/1212 2) (exit 5)
(let cell/1211 (load_mut int (+a switch/1210 0))
(if (== cell/1211 504403158265495552a) (exit 2) (exit 5)))))
with(5) 1a))
(exit 2))
with(2) 3a)
(catch
(if (!= (extcall "caml_equal"{a.ml:10,5-16} x/1005 "camlA__2" val) 1)
(if (!= ok/1006 1) (exit 4)
(app{a.ml:11,4-25} "camlPervasives__failwith_1005" "camlA__3" val))
(exit 4))
with(4) 1a)))

and the inlined cmm for A.trigger_bug inside B.bug is

(function{b.ml:1,8-27} camlB__bug_1002 (x/1003: val)
(let
ok/1008
(catch
(if (!= x/1003 1)
(let switch/1009 (load_mut val x/1003)
(catch
(let size/1011 (>>u (load_mut int (+a switch/1009 -8)) 10)
(if (>= size/1011 2) (exit 2)
(let cell/1010 (load_mut int (+a switch/1009 0))
(if (== cell/1010 504403158265495552a) (exit 2) (exit 2)))))
with(2) 1a))
(exit 2))
with(2) 3a)
(catch
(if (!= (extcall "caml_equal"{a.ml:10,5-16} x/1003 "camlA__2" val) 1)
(if (!= ok/1008 1) (exit 1)
(app{a.ml:11,4-25} "camlPervasives__failwith_1005" "camlA__3" val))
(exit 1))
with(1) 1a)))

which is wrong because the two different catch ids 2, 5 in the first (catch ...) term appear as 2, 2 when inlined.

@vicuna
Copy link
Author

vicuna commented Dec 31, 2017

Comment author: @nojb

I think the problem is in the "string matching" compiler in strmatch.ml.

@vicuna
Copy link
Author

vicuna commented Dec 31, 2017

Comment author: vlaviron

From a quick look: the bug comes from the cross-module inlining in closure.ml. Code loaded from external modules can contain staticfail indices that are bigger than Lambda.raise_count, which will cause the bug. This doesn't happen in flambda because flambda systematically recreates indices, but closure simply copies them, which is wrong with cross-module inlining.
I think the implementation of Closure.substitute from #1482 would make a good start, if anyone else wants to work on it.

@vicuna
Copy link
Author

vicuna commented Jan 2, 2018

Comment author: @xclerc

Tentative patch, following vlaviron suggestion: #1553

@vicuna
Copy link
Author

vicuna commented Jan 11, 2018

Comment author: @gasche

This was fixed in trunk by xclerc's pull request.

@vicuna vicuna closed this as completed Jan 11, 2018
@vicuna
Copy link
Author

vicuna commented Jan 11, 2018

Comment author: @xclerc

As suggest by hhugo in the PR, shouldn't this be
back ported to 4.06?

@vicuna
Copy link
Author

vicuna commented Jan 11, 2018

Comment author: @gasche

I don't know, and I don't have the bandwidth to deal with the question right now, so I just added a label on the PR.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants