Skip to content

Commit

Permalink
[macro] Catch eval runtime failures when decoding (#11633)
Browse files Browse the repository at this point in the history
* [eval] Catch runtime exceptions in safe_decode

* [macro] narrow build macro eval failures to individual field (hacky...)

* [tests] add test for 11632

* Less hacky way to retrieve haxe.macro.Field type

* [tests] remove unneeded import
  • Loading branch information
kLabz authored Apr 9, 2024
1 parent 323d2c4 commit 7217530
Show file tree
Hide file tree
Showing 8 changed files with 50 additions and 6 deletions.
1 change: 0 additions & 1 deletion src/macro/macroApi.ml
Original file line number Diff line number Diff line change
Expand Up @@ -846,7 +846,6 @@ and decode_field v =
}

and decode_ctype t =
if t = vnull then raise Invalid_expr;
let (i,args),p = decode_enum_with_pos t in
(match i,args with
| 0, [p] ->
Expand Down
17 changes: 12 additions & 5 deletions src/typing/macroContext.ml
Original file line number Diff line number Diff line change
Expand Up @@ -41,15 +41,20 @@ module HxbWriterConfigWriterEval = HxbWriterConfig.WriterConfigWriter(EvalDataAp
let macro_interp_cache = ref None

let safe_decode com v expected t p f =
try
f ()
with MacroApi.Invalid_expr ->
let raise_decode_error s =
let path = [dump_path com;"decoding_error"] in
let ch = Path.create_file false ".txt" [] path in
let errors = Interp.handle_decoding_error (output_string ch) v t in
List.iter (fun (s,i) -> Printf.fprintf ch "\nline %i: %s" i s) (List.rev errors);
close_out ch;
raise_typing_error (Printf.sprintf "Expected %s but got %s (see %s.txt for details)" expected (Interp.value_string v) (String.concat "/" path)) p
raise_typing_error (Printf.sprintf "%s (see %s.txt for details)" s (String.concat "/" path)) p
in

try f () with
| EvalContext.RunTimeException (VString emsg,_,_) ->
raise_decode_error (Printf.sprintf "Eval runtime exception: %s" emsg.sstring)
| MacroApi.Invalid_expr ->
raise_decode_error (Printf.sprintf "Expected %s but got %s" expected (Interp.value_string v))


let macro_timer com l =
Expand Down Expand Up @@ -960,7 +965,9 @@ let type_macro ctx mode cpath f (el:Ast.expr list) p =
| None -> die "" __LOC__
| Some (_,_,fields) -> fields)
else
List.map Interp.decode_field (Interp.decode_array v)
let ct = make_ptp_th (mk_type_path ~sub:"Field" (["haxe";"macro"], "Expr")) null_pos in
let t = Typeload.load_complex_type mctx false LoadNormal ct in
List.map (fun f -> safe_decode ctx.com f "Field" t p (fun () -> Interp.decode_field f)) (Interp.decode_array v)
in
MSuccess (EVars [mk_evar ~t:(CTAnonymous fields,p) ("fields",null_pos)],p)
)
Expand Down
15 changes: 15 additions & 0 deletions tests/misc/projects/Issue11632/Main.hx
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#if macro
import haxe.macro.Expr;
#end

#if !macro @:build(Macro.build()) #end
class Main {}

class Macro {
public static function build() {
var ct = TPath({pack: [], name: "Null", params: [TPType(null)]});
return (macro class {
var foo:$ct;
}).fields;
}
}
6 changes: 6 additions & 0 deletions tests/misc/projects/Issue11632/Test.hx
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import sys.io.File;

function main() {
var dump = File.getContent("dump/decoding_error.txt");
Sys.println(dump);
}
1 change: 1 addition & 0 deletions tests/misc/projects/Issue11632/compile-fail.hxml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
--main Main
1 change: 1 addition & 0 deletions tests/misc/projects/Issue11632/compile-fail.hxml.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Main.hx:5: characters 12-19 : Eval runtime exception: Null Access (see dump/decoding_error.txt for details)
1 change: 1 addition & 0 deletions tests/misc/projects/Issue11632/compile-test.hxml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
--run Test
14 changes: 14 additions & 0 deletions tests/misc/projects/Issue11632/compile-test.hxml.stdout
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
access: null
doc: null
kind: FVar(TPath({
name: Null
pack: []
params: [TPType(null <- expected enum value)]
sub: null
}), null)
meta: null
name: foo
pos: #pos
}
line 7: expected enum value

0 comments on commit 7217530

Please sign in to comment.