diff options
| author | Mike Pall <mike> | 2025-05-28 20:36:24 +0200 |
|---|---|---|
| committer | Mike Pall <mike> | 2025-05-28 20:36:24 +0200 |
| commit | 9c8eb7cfe10ef5939d9b358a0bd805a610818ba5 (patch) | |
| tree | cf87be0c0180e766c75f73b0a8164cbc6c8df928 /src | |
| parent | e76bb50d44702f601ec5dd167b03b475ed53860c (diff) | |
| download | luajit-9c8eb7cfe10ef5939d9b358a0bd805a610818ba5.tar.gz luajit-9c8eb7cfe10ef5939d9b358a0bd805a610818ba5.tar.bz2 luajit-9c8eb7cfe10ef5939d9b358a0bd805a610818ba5.zip | |
FFI: Fix dangling CType references.
Reported by Sergey Kaplun. Collateral of #1360
Diffstat (limited to 'src')
| -rw-r--r-- | src/lj_ccall.c | 19 | ||||
| -rw-r--r-- | src/lj_crecord.c | 21 |
2 files changed, 25 insertions, 15 deletions
diff --git a/src/lj_ccall.c b/src/lj_ccall.c index 9c99bec7..5d6bb03d 100644 --- a/src/lj_ccall.c +++ b/src/lj_ccall.c | |||
| @@ -623,7 +623,9 @@ noth: /* Not a homogeneous float/double aggregate. */ | |||
| 623 | 623 | ||
| 624 | /* -- Common C call handling ---------------------------------------------- */ | 624 | /* -- Common C call handling ---------------------------------------------- */ |
| 625 | 625 | ||
| 626 | /* Infer the destination CTypeID for a vararg argument. */ | 626 | /* Infer the destination CTypeID for a vararg argument. |
| 627 | ** Note: may reallocate cts->tab and invalidate CType pointers. | ||
| 628 | */ | ||
| 627 | CTypeID lj_ccall_ctid_vararg(CTState *cts, cTValue *o) | 629 | CTypeID lj_ccall_ctid_vararg(CTState *cts, cTValue *o) |
| 628 | { | 630 | { |
| 629 | if (tvisnumber(o)) { | 631 | if (tvisnumber(o)) { |
| @@ -651,13 +653,16 @@ CTypeID lj_ccall_ctid_vararg(CTState *cts, cTValue *o) | |||
| 651 | } | 653 | } |
| 652 | } | 654 | } |
| 653 | 655 | ||
| 654 | /* Setup arguments for C call. */ | 656 | /* Setup arguments for C call. |
| 657 | ** Note: may reallocate cts->tab and invalidate CType pointers. | ||
| 658 | */ | ||
| 655 | static int ccall_set_args(lua_State *L, CTState *cts, CType *ct, | 659 | static int ccall_set_args(lua_State *L, CTState *cts, CType *ct, |
| 656 | CCallState *cc) | 660 | CCallState *cc) |
| 657 | { | 661 | { |
| 658 | int gcsteps = 0; | 662 | int gcsteps = 0; |
| 659 | TValue *o, *top = L->top; | 663 | TValue *o, *top = L->top; |
| 660 | CTypeID fid; | 664 | CTypeID fid; |
| 665 | CTInfo info = ct->info; /* lj_ccall_ctid_vararg may invalidate ct pointer. */ | ||
| 661 | CType *ctr; | 666 | CType *ctr; |
| 662 | MSize maxgpr, ngpr = 0, nsp = 0, narg; | 667 | MSize maxgpr, ngpr = 0, nsp = 0, narg; |
| 663 | #if CCALL_NARG_FPR | 668 | #if CCALL_NARG_FPR |
| @@ -676,7 +681,7 @@ static int ccall_set_args(lua_State *L, CTState *cts, CType *ct, | |||
| 676 | #if LJ_TARGET_X86 | 681 | #if LJ_TARGET_X86 |
| 677 | /* x86 has several different calling conventions. */ | 682 | /* x86 has several different calling conventions. */ |
| 678 | cc->resx87 = 0; | 683 | cc->resx87 = 0; |
| 679 | switch (ctype_cconv(ct->info)) { | 684 | switch (ctype_cconv(info)) { |
| 680 | case CTCC_FASTCALL: maxgpr = 2; break; | 685 | case CTCC_FASTCALL: maxgpr = 2; break; |
| 681 | case CTCC_THISCALL: maxgpr = 1; break; | 686 | case CTCC_THISCALL: maxgpr = 1; break; |
| 682 | default: maxgpr = 0; break; | 687 | default: maxgpr = 0; break; |
| @@ -693,7 +698,7 @@ static int ccall_set_args(lua_State *L, CTState *cts, CType *ct, | |||
| 693 | } else if (ctype_iscomplex(ctr->info) || ctype_isstruct(ctr->info)) { | 698 | } else if (ctype_iscomplex(ctr->info) || ctype_isstruct(ctr->info)) { |
| 694 | /* Preallocate cdata object and anchor it after arguments. */ | 699 | /* Preallocate cdata object and anchor it after arguments. */ |
| 695 | CTSize sz = ctr->size; | 700 | CTSize sz = ctr->size; |
| 696 | GCcdata *cd = lj_cdata_new(cts, ctype_cid(ct->info), sz); | 701 | GCcdata *cd = lj_cdata_new(cts, ctype_cid(info), sz); |
| 697 | void *dp = cdataptr(cd); | 702 | void *dp = cdataptr(cd); |
| 698 | setcdataV(L, L->top++, cd); | 703 | setcdataV(L, L->top++, cd); |
| 699 | if (ctype_isstruct(ctr->info)) { | 704 | if (ctype_isstruct(ctr->info)) { |
| @@ -729,7 +734,7 @@ static int ccall_set_args(lua_State *L, CTState *cts, CType *ct, | |||
| 729 | lua_assert(ctype_isfield(ctf->info)); | 734 | lua_assert(ctype_isfield(ctf->info)); |
| 730 | did = ctype_cid(ctf->info); | 735 | did = ctype_cid(ctf->info); |
| 731 | } else { | 736 | } else { |
| 732 | if (!(ct->info & CTF_VARARG)) | 737 | if (!(info & CTF_VARARG)) |
| 733 | lj_err_caller(L, LJ_ERR_FFI_NUMARG); /* Too many arguments. */ | 738 | lj_err_caller(L, LJ_ERR_FFI_NUMARG); /* Too many arguments. */ |
| 734 | did = lj_ccall_ctid_vararg(cts, o); /* Infer vararg type. */ | 739 | did = lj_ccall_ctid_vararg(cts, o); /* Infer vararg type. */ |
| 735 | isva = 1; | 740 | isva = 1; |
| @@ -869,11 +874,11 @@ int lj_ccall_func(lua_State *L, GCcdata *cd) | |||
| 869 | ct = ctype_rawchild(cts, ct); | 874 | ct = ctype_rawchild(cts, ct); |
| 870 | } | 875 | } |
| 871 | if (ctype_isfunc(ct->info)) { | 876 | if (ctype_isfunc(ct->info)) { |
| 877 | CTypeID id = ctype_typeid(cts, ct); | ||
| 872 | CCallState cc; | 878 | CCallState cc; |
| 873 | int gcsteps, ret; | 879 | int gcsteps, ret; |
| 874 | cc.func = (void (*)(void))cdata_getptr(cdataptr(cd), sz); | 880 | cc.func = (void (*)(void))cdata_getptr(cdataptr(cd), sz); |
| 875 | gcsteps = ccall_set_args(L, cts, ct, &cc); | 881 | gcsteps = ccall_set_args(L, cts, ct, &cc); |
| 876 | ct = (CType *)((intptr_t)ct-(intptr_t)cts->tab); | ||
| 877 | cts->cb.slot = ~0u; | 882 | cts->cb.slot = ~0u; |
| 878 | lj_vm_ffi_call(&cc); | 883 | lj_vm_ffi_call(&cc); |
| 879 | if (cts->cb.slot != ~0u) { /* Blacklist function that called a callback. */ | 884 | if (cts->cb.slot != ~0u) { /* Blacklist function that called a callback. */ |
| @@ -881,7 +886,7 @@ int lj_ccall_func(lua_State *L, GCcdata *cd) | |||
| 881 | setlightudV(&tv, (void *)cc.func); | 886 | setlightudV(&tv, (void *)cc.func); |
| 882 | setboolV(lj_tab_set(L, cts->miscmap, &tv), 1); | 887 | setboolV(lj_tab_set(L, cts->miscmap, &tv), 1); |
| 883 | } | 888 | } |
| 884 | ct = (CType *)((intptr_t)ct+(intptr_t)cts->tab); /* May be reallocated. */ | 889 | ct = ctype_get(cts, id); /* Table may have been reallocated. */ |
| 885 | gcsteps += ccall_get_results(L, cts, ct, &cc, &ret); | 890 | gcsteps += ccall_get_results(L, cts, ct, &cc, &ret); |
| 886 | #if LJ_TARGET_X86 && LJ_ABI_WIN | 891 | #if LJ_TARGET_X86 && LJ_ABI_WIN |
| 887 | /* Automatically detect __stdcall and fix up C function declaration. */ | 892 | /* Automatically detect __stdcall and fix up C function declaration. */ |
diff --git a/src/lj_crecord.c b/src/lj_crecord.c index 216144f3..f686b35f 100644 --- a/src/lj_crecord.c +++ b/src/lj_crecord.c | |||
| @@ -988,12 +988,15 @@ static void crec_alloc(jit_State *J, RecordFFData *rd, CTypeID id) | |||
| 988 | } | 988 | } |
| 989 | } | 989 | } |
| 990 | 990 | ||
| 991 | /* Record argument conversions. */ | 991 | /* Record argument conversions. |
| 992 | ** Note: may reallocate cts->tab and invalidate CType pointers. | ||
| 993 | */ | ||
| 992 | static TRef crec_call_args(jit_State *J, RecordFFData *rd, | 994 | static TRef crec_call_args(jit_State *J, RecordFFData *rd, |
| 993 | CTState *cts, CType *ct) | 995 | CTState *cts, CType *ct) |
| 994 | { | 996 | { |
| 995 | TRef args[CCI_NARGS_MAX]; | 997 | TRef args[CCI_NARGS_MAX]; |
| 996 | CTypeID fid; | 998 | CTypeID fid; |
| 999 | CTInfo info = ct->info; /* lj_ccall_ctid_vararg may invalidate ct pointer. */ | ||
| 997 | MSize i, n; | 1000 | MSize i, n; |
| 998 | TRef tr, *base; | 1001 | TRef tr, *base; |
| 999 | cTValue *o; | 1002 | cTValue *o; |
| @@ -1002,9 +1005,9 @@ static TRef crec_call_args(jit_State *J, RecordFFData *rd, | |||
| 1002 | TRef *arg0 = NULL, *arg1 = NULL; | 1005 | TRef *arg0 = NULL, *arg1 = NULL; |
| 1003 | #endif | 1006 | #endif |
| 1004 | int ngpr = 0; | 1007 | int ngpr = 0; |
| 1005 | if (ctype_cconv(ct->info) == CTCC_THISCALL) | 1008 | if (ctype_cconv(info) == CTCC_THISCALL) |
| 1006 | ngpr = 1; | 1009 | ngpr = 1; |
| 1007 | else if (ctype_cconv(ct->info) == CTCC_FASTCALL) | 1010 | else if (ctype_cconv(info) == CTCC_FASTCALL) |
| 1008 | ngpr = 2; | 1011 | ngpr = 2; |
| 1009 | #endif | 1012 | #endif |
| 1010 | 1013 | ||
| @@ -1029,7 +1032,7 @@ static TRef crec_call_args(jit_State *J, RecordFFData *rd, | |||
| 1029 | lua_assert(ctype_isfield(ctf->info)); | 1032 | lua_assert(ctype_isfield(ctf->info)); |
| 1030 | did = ctype_cid(ctf->info); | 1033 | did = ctype_cid(ctf->info); |
| 1031 | } else { | 1034 | } else { |
| 1032 | if (!(ct->info & CTF_VARARG)) | 1035 | if (!(info & CTF_VARARG)) |
| 1033 | lj_trace_err(J, LJ_TRERR_NYICALL); /* Too many arguments. */ | 1036 | lj_trace_err(J, LJ_TRERR_NYICALL); /* Too many arguments. */ |
| 1034 | did = lj_ccall_ctid_vararg(cts, o); /* Infer vararg type. */ | 1037 | did = lj_ccall_ctid_vararg(cts, o); /* Infer vararg type. */ |
| 1035 | } | 1038 | } |
| @@ -1112,12 +1115,14 @@ static int crec_call(jit_State *J, RecordFFData *rd, GCcdata *cd) | |||
| 1112 | { | 1115 | { |
| 1113 | CTState *cts = ctype_ctsG(J2G(J)); | 1116 | CTState *cts = ctype_ctsG(J2G(J)); |
| 1114 | CType *ct = ctype_raw(cts, cd->ctypeid); | 1117 | CType *ct = ctype_raw(cts, cd->ctypeid); |
| 1118 | CTInfo info; | ||
| 1115 | IRType tp = IRT_PTR; | 1119 | IRType tp = IRT_PTR; |
| 1116 | if (ctype_isptr(ct->info)) { | 1120 | if (ctype_isptr(ct->info)) { |
| 1117 | tp = (LJ_64 && ct->size == 8) ? IRT_P64 : IRT_P32; | 1121 | tp = (LJ_64 && ct->size == 8) ? IRT_P64 : IRT_P32; |
| 1118 | ct = ctype_rawchild(cts, ct); | 1122 | ct = ctype_rawchild(cts, ct); |
| 1119 | } | 1123 | } |
| 1120 | if (ctype_isfunc(ct->info)) { | 1124 | info = ct->info; /* crec_call_args may invalidate ct pointer. */ |
| 1125 | if (ctype_isfunc(info)) { | ||
| 1121 | TRef func = emitir(IRT(IR_FLOAD, tp), J->base[0], IRFL_CDATA_PTR); | 1126 | TRef func = emitir(IRT(IR_FLOAD, tp), J->base[0], IRFL_CDATA_PTR); |
| 1122 | CType *ctr = ctype_rawchild(cts, ct); | 1127 | CType *ctr = ctype_rawchild(cts, ct); |
| 1123 | IRType t = crec_ct2irt(cts, ctr); | 1128 | IRType t = crec_ct2irt(cts, ctr); |
| @@ -1135,9 +1140,9 @@ static int crec_call(jit_State *J, RecordFFData *rd, GCcdata *cd) | |||
| 1135 | ctype_isenum(ctr->info)) || t == IRT_CDATA) { | 1140 | ctype_isenum(ctr->info)) || t == IRT_CDATA) { |
| 1136 | lj_trace_err(J, LJ_TRERR_NYICALL); | 1141 | lj_trace_err(J, LJ_TRERR_NYICALL); |
| 1137 | } | 1142 | } |
| 1138 | if ((ct->info & CTF_VARARG) | 1143 | if ((info & CTF_VARARG) |
| 1139 | #if LJ_TARGET_X86 | 1144 | #if LJ_TARGET_X86 |
| 1140 | || ctype_cconv(ct->info) != CTCC_CDECL | 1145 | || ctype_cconv(info) != CTCC_CDECL |
| 1141 | #endif | 1146 | #endif |
| 1142 | ) | 1147 | ) |
| 1143 | func = emitir(IRT(IR_CARG, IRT_NIL), func, | 1148 | func = emitir(IRT(IR_CARG, IRT_NIL), func, |
| @@ -1160,7 +1165,7 @@ static int crec_call(jit_State *J, RecordFFData *rd, GCcdata *cd) | |||
| 1160 | } | 1165 | } |
| 1161 | } else if (t == IRT_PTR || (LJ_64 && t == IRT_P32) || | 1166 | } else if (t == IRT_PTR || (LJ_64 && t == IRT_P32) || |
| 1162 | t == IRT_I64 || t == IRT_U64 || ctype_isenum(ctr->info)) { | 1167 | t == IRT_I64 || t == IRT_U64 || ctype_isenum(ctr->info)) { |
| 1163 | TRef trid = lj_ir_kint(J, ctype_cid(ct->info)); | 1168 | TRef trid = lj_ir_kint(J, ctype_cid(info)); |
| 1164 | tr = emitir(IRTG(IR_CNEWI, IRT_CDATA), trid, tr); | 1169 | tr = emitir(IRTG(IR_CNEWI, IRT_CDATA), trid, tr); |
| 1165 | if (t == IRT_I64 || t == IRT_U64) lj_needsplit(J); | 1170 | if (t == IRT_I64 || t == IRT_U64) lj_needsplit(J); |
| 1166 | } else if (t == IRT_FLOAT || t == IRT_U32) { | 1171 | } else if (t == IRT_FLOAT || t == IRT_U32) { |
