Skip to content

Commit 7aee14b

Browse files
authored
Merge pull request #331 from VSharp-team/unsafe-fixes
Unsafe fixes
2 parents fa3fed0 + 8cdc162 commit 7aee14b

File tree

3 files changed

+112
-20
lines changed

3 files changed

+112
-20
lines changed

VSharp.SILI.Core/Memory.fs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1089,7 +1089,12 @@ module internal Memory =
10891089
match elementOffset.term with
10901090
| Concrete(:? int as i, _) when (i + viewSize) % concreteElementSize = 0 -> (i + viewSize) / concreteElementSize
10911091
// NOTE: if offset inside element > 0 then one more element is needed
1092-
| _ -> (viewSize / concreteElementSize) + 1
1092+
| _ ->
1093+
let count = (viewSize / concreteElementSize) + 1
1094+
// it is possible that two elements are affected, so we add 1, otherwise reading result will be
1095+
// an empty slice
1096+
if viewSize % concreteElementSize >= 2 then count + 1
1097+
else count
10931098
let getElement currentOffset i =
10941099
let linearIndex = makeNumber i |> add firstElement
10951100
let indices = delinearizeArrayIndex linearIndex lens lbs

VSharp.Solver/Z3.fs

Lines changed: 7 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -722,12 +722,6 @@ module internal Z3 =
722722
elif exprSize > size then ctx.MkExtract(size - 1u, 0u, expr)
723723
else ctx.MkSignExt(size - exprSize, expr)
724724

725-
member private x.ReverseBytes (expr : BitVecExpr) =
726-
let size = int expr.SortSize
727-
assert(size % 8 = 0)
728-
let bytes = List.init (size / 8) (fun byte -> ctx.MkExtract(uint ((byte + 1) * 8) - 1u, uint (byte * 8), expr))
729-
List.reduce (fun x y -> ctx.MkConcat(x, y)) bytes
730-
731725
member private x.ComputeSliceBounds assumptions cuts termSortSize =
732726
assert(termSortSize % 8u = 0u && termSortSize > 0u)
733727
let zero = ctx.MkBV(0, termSortSize)
@@ -806,10 +800,8 @@ module internal Z3 =
806800
| _ -> x.EncodeTerm slice, List.empty
807801

808802
member private x.EncodeCombine slices typ =
809-
let size = x.SizeOfBV typ
810-
let res = ctx.MkBV(0, size)
811-
let window = res.SortSize
812-
let windowExpr = ctx.MkNumeral(window, x.Type2Sort(Types.IndexType)) :?> BitVecExpr
803+
let window = x.SizeOfBV typ
804+
let res = ctx.MkBV(0, window)
813805
let addOneSlice (res, assumptions) slice =
814806
let term, cuts = x.EncodeSlice slice
815807
let t =
@@ -831,25 +823,21 @@ module internal Z3 =
831823
let sliceSize = x.MkBVSub(rBit, lBit)
832824
let zero = ctx.MkBV(0, termSize)
833825
let intersects = x.MkBVSGT(sliceSize, zero)
834-
let term = x.ReverseBytes t
835826
let left = x.ExtractOrExtend lBit termSize
836-
let term = x.MkBVShl(term, left)
837-
let cutRight = x.ExtractOrExtend (x.MkBVSub(sizeExpr, rBit)) termSize
827+
let right = x.ExtractOrExtend rBit termSize
828+
let cutRight = x.MkBVSub(sizeExpr, right)
829+
let term = x.MkBVShl(t, cutRight)
838830
let term = x.MkBVLShr(term, x.MkBVAdd(left, cutRight))
839831
let term =
840832
if termSize > window then ctx.MkExtract(window - 1u, 0u, term)
841833
else ctx.MkZeroExt(window - termSize, term)
842834
let changedTermSize = term.SortSize
843-
let w = x.ExtractOrExtend windowExpr changedTermSize
844835
let pos = x.ExtractOrExtend posBit changedTermSize
845-
let sliceSize = x.ExtractOrExtend sliceSize changedTermSize
846-
let shift = x.MkBVSub(w, x.MkBVAdd(pos, sliceSize))
847-
let part = x.MkBVShl(term, shift)
836+
let part = x.MkBVShl(term, pos)
848837
let res = x.MkITE(intersects, x.MkBVOr(res, part), res) :?> BitVecExpr
849838
res, assumptions
850839
let result, assumptions = List.fold addOneSlice (res, List.empty) slices
851-
let result = x.ReverseBytes result
852-
let result = x.CreateCombineResult result typ size
840+
let result = x.CreateCombineResult result typ window
853841
{expr = result; assumptions = assumptions}
854842

855843
member private x.EncodeApplication sf typ (args : Expr array) =

VSharp.Test/Tests/Unsafe.cs

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -335,6 +335,89 @@ public static bool ArraySymbolicUnsafeWrite(int i)
335335
else
336336
return true;
337337
}
338+
339+
[TestSvm(95)]
340+
public static bool ArraySymbolicUnsafeWrite11(int i, int j)
341+
{
342+
var array = new long[] {1, 2, 3, 4, 5};
343+
fixed (long* ptr = &array[0])
344+
{
345+
var ptr2 = (byte*) ptr;
346+
var ptr3 = ptr2 + i;
347+
*ptr3 = 67;
348+
var ptr4 = (int*)(ptr2 + j);
349+
*ptr4 = 23181328;
350+
}
351+
352+
if (i == 1 && j == 2 && array[0] != 1519211528961L)
353+
return false;
354+
355+
return true;
356+
}
357+
358+
[TestSvm(95)]
359+
public static bool ArraySymbolicUnsafeWrite12(int i, int j)
360+
{
361+
var array = new long[] { 1, 2, 3, 4, 5 };
362+
fixed (long* ptr = &array[0])
363+
{
364+
var ptr1 = (byte*) ptr;
365+
var ptr3 = (int*)(ptr1 + i);
366+
*ptr3 = 67;
367+
var ptr4 = (byte*)(ptr1 + i);
368+
*ptr4 = 87;
369+
}
370+
371+
if (i == 2 && array[0] != 5701633)
372+
return false;
373+
374+
return true;
375+
}
376+
377+
[TestSvm(94)]
378+
public static bool ArrayWriteTargetingTwoElements(int i, int j)
379+
{
380+
var array = new long[] { 1, 2, 3, 4, 5 };
381+
fixed (long* ptr = &array[0])
382+
{
383+
var ptr1 = (byte*) ptr;
384+
var ptr3 = (short*)(ptr1 + i);
385+
*ptr3 = 67;
386+
}
387+
388+
if (i == 7 && array[1] == 2)
389+
return false;
390+
391+
return true;
392+
}
393+
394+
struct SomeStruct
395+
{
396+
public int x1;
397+
public int x2;
398+
public int x3;
399+
public int x4;
400+
public int x5;
401+
}
402+
403+
[TestSvm(96)]
404+
public static bool ArrayWriteTargetingThreeElements(int i, int j)
405+
{
406+
var array = new long[] { 1, 2, 3, 4, 5 };
407+
fixed (long* ptr = &array[0])
408+
{
409+
var ptr1 = (byte*) ptr;
410+
var ptr3 = (SomeStruct*)(ptr1 + i);
411+
var value = new SomeStruct() {x1 = 4455, x2 = 4143, x3 = 31323, x4 = 44, x5 = 3243};
412+
*ptr3 = value;
413+
}
414+
415+
// array[3] is affected by writing struct
416+
if (i == 6 && array[3] == 4)
417+
return false;
418+
419+
return true;
420+
}
338421

339422
[TestSvm(97)]
340423
public static bool ArraySymbolicUnsafeWrite2(int i)
@@ -808,6 +891,22 @@ public static int DoubleReinterpretation(long a, int i, int j)
808891
*ptr = v;
809892
return *(int*)((byte*)ptr + j);
810893
}
894+
895+
[TestSvm(94)]
896+
public static bool DoubleReinterpretation4(long a, int i, int j)
897+
{
898+
var b = a;
899+
var p = &a;
900+
var ptr = (int*)((byte*)p + i);
901+
var v = *ptr;
902+
ptr = (int*)((byte *)p + i);
903+
*ptr = v;
904+
var p2 = &b;
905+
var ptr2 = (int*)((byte*)p2 + i);
906+
if (*(int*)((byte*)ptr + j) == *(int*)((byte*)ptr2 + j))
907+
return true;
908+
return false;
909+
}
811910

812911
[TestSvm(100)]
813912
public static int DoubleReinterpretation1(int[] arr, int i, int j)

0 commit comments

Comments
 (0)