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
Comments
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) and the inlined cmm for A.trigger_bug inside B.bug is (function{b.ml:1,8-27} camlB__bug_1002 (x/1003: val) which is wrong because the two different catch ids 2, 5 in the first (catch ...) term appear as 2, 2 when inlined. |
Comment author: @nojb I think the problem is in the "string matching" compiler in strmatch.ml. |
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. |
Comment author: @gasche This was fixed in trunk by xclerc's pull request. |
Comment author: @xclerc As suggest by hhugo in the PR, shouldn't this be |
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. |
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
The text was updated successfully, but these errors were encountered: