disallow writing array to pointer within pointer object
and while at it move a global to an argument
This commit is contained in:
parent
74f7e4701d
commit
2b30010c25
52
src/ffi.c
52
src/ffi.c
@ -681,16 +681,15 @@ static NOINLINE B ty_fmt(B o) {
|
||||
|
||||
|
||||
|
||||
STATIC_GLOBAL B ffiObjsGlobal;
|
||||
static void genObj_ptrobj(void* res, B c, B expEl) {
|
||||
static void genObj_writePtr(void* res, B c, B expEl, B* sourceObjs) {
|
||||
B h = ptrobj_checkget(c);
|
||||
#if FFI_CHECKS
|
||||
if (!ty_equal(ptrh_type(h), expEl)) thrF("FFI: Pointer object type isn't compatible with argument type");
|
||||
#endif
|
||||
ffiObjsGlobal = vec_addN(ffiObjsGlobal, incG(c));
|
||||
*(void**)res = ptrh_ptr(h);
|
||||
if (sourceObjs!=NULL) *sourceObjs = vec_addN(*sourceObjs, incG(c));
|
||||
}
|
||||
void genObj(B o, B c, void* ptr) { // doesn't consume; mutates ffiObjsGlobal
|
||||
void genObj(B o, B c, void* ptr, B* sourceObjs) { // doesn't consume
|
||||
if (isC32(o)) { // scalar
|
||||
u32 t = styG(o);
|
||||
f64 f = c.f;
|
||||
@ -712,9 +711,10 @@ void genObj(B o, B c, void* ptr) { // doesn't consume; mutates ffiObjsGlobal
|
||||
if (t->ty==cty_ptr || t->ty==cty_tlarr) { // *any / &any / top-level [n]any
|
||||
B e = t->a[0].o;
|
||||
if (isAtm(c)) {
|
||||
if (isNsp(c)) { genObj_ptrobj(ptr, c, e); return; }
|
||||
if (isNsp(c)) { genObj_writePtr(ptr, c, e, sourceObjs); return; }
|
||||
thrF("FFI: Expected array or pointer object corresponding to %R", ty_fmt(o));
|
||||
}
|
||||
if (sourceObjs==NULL) thrF("ptr.Write: Cannot write array to %R", ty_fmt(o));
|
||||
usz ia = IA(c);
|
||||
if (t->ty==cty_tlarr && t->arrCount!=ia) thrF("FFI: Incorrect item count of %s corresponding to %R", ia, ty_fmt(o));
|
||||
if (isC32(e)) { // *num / &num
|
||||
@ -732,8 +732,8 @@ void genObj(B o, B c, void* ptr) { // doesn't consume; mutates ffiObjsGlobal
|
||||
case sty_f32: ffi_checkRange(c, mut, "f64", 0, 0); cG = cpyF32Bits(c); break; // no direct f32 type, so no direct reference option
|
||||
}
|
||||
|
||||
ffiObjsGlobal = vec_addN(ffiObjsGlobal, cG);
|
||||
*(void**)ptr = tyany_ptr(cG);
|
||||
*sourceObjs = vec_addN(*sourceObjs, cG);
|
||||
} else { // *{...} / &{...} / *[n]any
|
||||
BQNFFIType* t2 = c(BQNFFIType, e);
|
||||
if (t2->ty!=cty_struct && t2->ty!=cty_starr) thrM("FFI: Pointer element type not implemented");
|
||||
@ -743,9 +743,9 @@ void genObj(B o, B c, void* ptr) { // doesn't consume; mutates ffiObjsGlobal
|
||||
void* dataStruct = dataAll+sizeof(usz);
|
||||
*((usz*)dataAll) = ia;
|
||||
SGetU(c)
|
||||
for (usz i = 0; i < ia; i++) genObj(t->a[0].o, GetU(c, i), dataStruct + elSz*i);
|
||||
for (usz i = 0; i < ia; i++) genObj(t->a[0].o, GetU(c, i), dataStruct + elSz*i, sourceObjs);
|
||||
*(void**)ptr = dataStruct;
|
||||
ffiObjsGlobal = vec_addN(ffiObjsGlobal, tag(TOBJ(dataAll), OBJ_TAG));
|
||||
*sourceObjs = vec_addN(*sourceObjs, tag(TOBJ(dataAll), OBJ_TAG));
|
||||
}
|
||||
} else if (t->ty==cty_repr) { // any:any
|
||||
B o2 = t->a[0].o;
|
||||
@ -765,11 +765,12 @@ void genObj(B o, B c, void* ptr) { // doesn't consume; mutates ffiObjsGlobal
|
||||
BQNFFIType* t2 = c(BQNFFIType, o2);
|
||||
B ore = t2->a[0].o;
|
||||
assert(t2->ty==cty_ptr && (isC32(ore) || ore.u==ty_voidptr.u));
|
||||
if (isNsp(c)) { genObj_ptrobj(ptr, c, ore); return; }
|
||||
if (isNsp(c)) { genObj_writePtr(ptr, c, ore, sourceObjs); return; }
|
||||
if (ore.u == m_c32(sty_void).u) { // *:any
|
||||
elSz = sizeof(void*);
|
||||
goto toScalarReinterpret;
|
||||
}
|
||||
if (sourceObjs==NULL) thrF("ptr.Write: Cannot write array to %R", ty_fmt(o));
|
||||
bool mut = t2->mutPtr;
|
||||
|
||||
elSz = isC32(ore)? sty_w[styG(ore)] : sizeof(void*);
|
||||
@ -790,7 +791,7 @@ void genObj(B o, B c, void* ptr) { // doesn't consume; mutates ffiObjsGlobal
|
||||
cG = taga(cGp);
|
||||
} else cG = toW(reT, reW, c);
|
||||
*(void**)ptr = tyany_ptr(cG);
|
||||
ffiObjsGlobal = vec_addN(ffiObjsGlobal, cG);
|
||||
*sourceObjs = vec_addN(*sourceObjs, cG);
|
||||
}
|
||||
} else if (t->ty==cty_struct || t->ty==cty_starr) {
|
||||
if (!isArr(c)) thrF("FFI: Expected array corresponding to %R", ty_fmt(o));
|
||||
@ -798,7 +799,7 @@ void genObj(B o, B c, void* ptr) { // doesn't consume; mutates ffiObjsGlobal
|
||||
SGetU(c)
|
||||
for (usz i = 0; i < t->ia-1; i++) {
|
||||
BQNFFIEnt e = t->a[i];
|
||||
genObj(e.o, GetU(c, i), e.structOffset + (u8*)ptr);
|
||||
genObj(e.o, GetU(c, i), e.structOffset + (u8*)ptr, sourceObjs);
|
||||
}
|
||||
} else thrM("FFI: Unimplemented type (genObj)");
|
||||
}
|
||||
@ -816,19 +817,17 @@ static B readStruct(BQNFFIType* t, u8* ptr) {
|
||||
}
|
||||
|
||||
static B readSimple(u8 resCType, u8* ptr) {
|
||||
B r;
|
||||
switch(resCType) { default: UD; // thrM("FFI: Unimplemented type");
|
||||
case sty_void: r = m_c32(0); break;
|
||||
case sty_a: r = getB(*(BQNV*)ptr); break;
|
||||
case sty_i8: r = m_i32(*( i8*)ptr); break; case sty_u8: r = m_i32(*( u8*)ptr); break;
|
||||
case sty_i16: r = m_i32(*(i16*)ptr); break; case sty_u16: r = m_i32(*(u16*)ptr); break;
|
||||
case sty_i32: r = m_i32(*(i32*)ptr); break; case sty_u32: r = m_f64(*(u32*)ptr); break;
|
||||
case sty_i64: { i64 v = *(i64*)ptr; if (i64abs(v)>=(1ULL<<53)) thrM("FFI: i64 result absolute value ≥ 2⋆53"); r = m_f64(v); break; }
|
||||
case sty_u64: { u64 v = *(u64*)ptr; if ( v >=(1ULL<<53)) thrM("FFI: u64 result ≥ 2⋆53"); r = m_f64(v); break; }
|
||||
case sty_f32: r = m_f64(*(float* )ptr); break;
|
||||
case sty_f64: r = m_f64(*(double*)ptr); break;
|
||||
case sty_void:return m_c32(0);
|
||||
case sty_a: return getB(*(BQNV*)ptr);
|
||||
case sty_i8: return m_i32(*( i8*)ptr); case sty_u8: return m_i32(*( u8*)ptr);
|
||||
case sty_i16: return m_i32(*(i16*)ptr); case sty_u16: return m_i32(*(u16*)ptr);
|
||||
case sty_i32: return m_i32(*(i32*)ptr); case sty_u32: return m_f64(*(u32*)ptr);
|
||||
case sty_i64: { i64 v = *(i64*)ptr; if (i64abs(v)>=(1ULL<<53)) thrM("FFI: i64 result absolute value ≥ 2⋆53"); return m_f64(v); }
|
||||
case sty_u64: { u64 v = *(u64*)ptr; if ( v >=(1ULL<<53)) thrM("FFI: u64 result ≥ 2⋆53"); return m_f64(v); }
|
||||
case sty_f32: return m_f64(*(float* )ptr);
|
||||
case sty_f64: return m_f64(*(double*)ptr);
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
static u8 const reTyMapC[] = { [3]=t_c8arr, [4]=t_c16arr, [5]=t_c32arr };
|
||||
@ -940,7 +939,7 @@ B libffiFn_c2(B t, B w, B x) {
|
||||
usz argn = cif->nargs;
|
||||
|
||||
BQNFFIEnt* ents = argObj->a;
|
||||
ffiObjsGlobal = emptyHVec(); // implicit parameter to genObj
|
||||
B ffiObjs = emptyHVec(); // implicit parameter to genObj
|
||||
for (usz i = 0; i < argn; i++) {
|
||||
BQNFFIEnt e = ents[i+1];
|
||||
B o;
|
||||
@ -949,9 +948,8 @@ B libffiFn_c2(B t, B w, B x) {
|
||||
} else {
|
||||
o = (e.onW? wf : xf)(e.onW?wa:xa, idxs[e.onW]++);
|
||||
}
|
||||
genObj(e.o, o, tmpAlloc + e.staticOffset);
|
||||
genObj(e.o, o, tmpAlloc + e.staticOffset, &ffiObjs);
|
||||
}
|
||||
B ffiObjs = ffiObjsGlobal; // load the global before ffi_call to prevent issues on recursive calls
|
||||
|
||||
for (usz i = 0; i < argn; i++) argPtrs[i] = tmpAlloc + ents[i+1].staticOffset;
|
||||
void* res = tmpAlloc + ents[0].staticOffset;
|
||||
@ -1228,9 +1226,7 @@ static B ptrobjRead_c1(B t, B x) {
|
||||
}
|
||||
static B ptrobjWrite_c2(B t, B w, B x) {
|
||||
B h = nfn_objU(t);
|
||||
ffiObjsGlobal = emptyHVec();
|
||||
genObj(ptrh_type(h), x, ptrobj_elbase(h, w, false));
|
||||
decG(ffiObjsGlobal);
|
||||
genObj(ptrh_type(h), x, ptrobj_elbase(h, w, false), NULL);
|
||||
|
||||
dec(x);
|
||||
return m_f64(1);
|
||||
|
||||
@ -75,6 +75,7 @@
|
||||
!"FFI: Return value is specified as ""&"", but there are 0 mutated values" % @•FFI"&"‿"bqn_init"‿">*i32"
|
||||
!"FFI: Return value is specified as ""&"", but there are 2 mutated values" % @•FFI"&"‿"bqn_init"‿"&i32"‿"&i32"
|
||||
!"FFI: Cannot return array" % @•FFI"[4]i32"‿"bqn_init"
|
||||
!"FFI: Unimplemented result type" % @•FFI"**:i8"‿"bqn_init"
|
||||
|
||||
|
||||
# correct elements
|
||||
@ -195,6 +196,9 @@
|
||||
%USE Walloc {{𝕊al: p←"{i16,i16,i16,i64}" Al 99 ⋄ p.Write ¯4‿10000‿¯30000‿7e12 ⋄ s←-○{CpyA 0∾˜⋈˜𝕩}´ ⟨p.Field 2, p⟩ ⋄ Cpy ⟨p.Add 1, p, s⟩ ⋄ p.Read¨ ↕2}} %% ⟨¯4‿10000‿¯30000‿7e12, ¯4‿10000‿0‿0⟩
|
||||
%USE Walloc {{𝕊al: p←"{i32,{i64,i64}}" Al 999 ⋄ {𝕩 p.Write ⟨𝕩×10,𝕩×20‿30⟩}¨ ↕4 ⋄ ((p.Field 1).Field 0).Read¨ ↕4 }} %% 20×↕4
|
||||
!"Cannot get a field of a pointer to a scalar" % %USE WallocE {{𝕊al: ("i32" Al 99).Field 0}}
|
||||
!"ptr.Write: Cannot write array to ""*i32""" % %USE WallocE {{𝕊al: ("*i32" Al 99).Write 1‿2‿3}}
|
||||
!"ptr.Write: Cannot write array to ""*i32:i32""" % %USE WallocE {{𝕊al: ("*i32:i32"Al 99).Write ↕16}}
|
||||
%USE Walloc {{𝕊al: p←("" Al 99).Cast "*:i8" ⋄ a←"i32"Al 99 ⋄ a.Write 12345 ⋄ p.Write ar←Cpy a‿a‿0 ⋄ ! ar ≡ p.Read 0 ⋄ a.Read 0}} %% 12345
|
||||
%USE Walloc {{𝕊al: p←"i16" Al 99 ⋄ raw ← Cpy 0∾˜⋈˜p.Add 3 ⋄ cpy2←@•FFI"*i16"‿"memcpy"‿"*:i8"‿"*:i8"‿size_t ⋄ p.Sub Cpy2 raw‿raw‿0 }} %% ¯3
|
||||
|
||||
# garbage arguments
|
||||
|
||||
Loading…
Reference in New Issue
Block a user