Skip to content

Commit 72b01b1

Browse files
varad64varad64
and
varad64
authored
Apply patches for #295 to explore bit-flip manipulation and #297 and #299 to fix and refactor the Verify class (#403)
Co-authored-by: varad64 <[email protected]>
1 parent 1705f95 commit 72b01b1

File tree

17 files changed

+1002
-58
lines changed

17 files changed

+1002
-58
lines changed
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package gov.nasa.jpf.annotation;
2+
3+
import java.lang.annotation.ElementType;
4+
import java.lang.annotation.Retention;
5+
import java.lang.annotation.RetentionPolicy;
6+
import java.lang.annotation.Target;
7+
8+
/**
9+
* @author Pu Yi <[email protected]>
10+
*
11+
* An annotation used to specify fields/parameters to perform bit flipping exploration
12+
*/
13+
@Retention(RetentionPolicy.RUNTIME)
14+
@Target({ ElementType.PARAMETER, ElementType.FIELD, ElementType.LOCAL_VARIABLE })
15+
public @interface BitFlip {
16+
int value() default 1;
17+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package fault.injection.examples;
2+
3+
import gov.nasa.jpf.vm.Verify;
4+
5+
/*
6+
* Use getBitFlip API to inject a bit flip to a variable
7+
*/
8+
public class APISimpleExample {
9+
public static void main(String[] args) {
10+
System.out.println(Verify.getBitFlip((byte)0, 2));
11+
}
12+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package fault.injection.examples;
2+
3+
import gov.nasa.jpf.vm.Verify;
4+
import gov.nasa.jpf.annotation.BitFlip;
5+
6+
/*
7+
* Use @BitFlip annotation to inject a bit flip to an argument
8+
*/
9+
public class AnnotationSimpleExample {
10+
public static void foo(@BitFlip byte bar) {
11+
System.out.println(bar);
12+
}
13+
public static void main(String[] args) {
14+
foo((byte)0);
15+
}
16+
}
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
package fault.injection.examples;
2+
3+
import gov.nasa.jpf.vm.Verify;
4+
5+
/*
6+
* International Standard Book Number (ISBN) error detection
7+
* BCD variant
8+
*/
9+
public class BCDEncodedISBN {
10+
11+
// get the i-th (indexed from 0) decimal number
12+
static int getNumber (long digits, int i) {
13+
return (int) ((digits >> (i << 2)) & 15);
14+
}
15+
16+
// calculate the check digit for ISBN-10 based on the first 9 digits
17+
public static int calculate10 (long digits) {
18+
int s = 0, t = 0;
19+
for (int i = 0; i < 9; ++i) {
20+
int digit = getNumber(digits, i);
21+
t += digit;
22+
s += t;
23+
}
24+
return (11 - (s + t) % 11) % 11;
25+
}
26+
27+
// ISBN-10 check
28+
public static boolean check10 (long digits) {
29+
// invalid if more than 10 decimal numbers
30+
if ((digits >> 40) != 0)
31+
return false;
32+
for (int i = 0; i < 10; ++i) {
33+
if (getNumber(digits, i) > 10 || (getNumber(digits, i) == 10 && i != 9))
34+
return false;
35+
}
36+
return getNumber(digits, 9) == calculate10(digits);
37+
}
38+
39+
// calculate the check digit for ISBN-13 based on the first 12 digits
40+
public static int calculate13 (long digits) {
41+
int s = 0, t = 1;
42+
for (int i = 0; i < 12; ++i) {
43+
s += getNumber(digits, i) * t;
44+
t = 4 - t;
45+
}
46+
return (10 - s % 10) % 10;
47+
}
48+
49+
// ISBN-13 check
50+
public static boolean check13 (long digits) {
51+
// invalid if more than 13 decimal numbers
52+
if ((digits >> 52) != 0)
53+
return false;
54+
for (int i = 0; i < 13; ++i) {
55+
if (getNumber(digits, i) < 0 || getNumber(digits, i) > 9)
56+
return false;
57+
}
58+
return getNumber(digits, 12) == calculate13(digits);
59+
}
60+
61+
// given the first 9 digits, generate the 10th, and check that one bit flip will always be detected
62+
public static void main (String[] args) {
63+
assert (args[0].length() == 9);
64+
long digits = 0;
65+
for (int i = 0; i < 9; ++i) {
66+
char c = args[0].charAt(i);
67+
assert (c >= '0' && c <= '9');
68+
digits |= ((long) (c - '0')) << (i << 2);
69+
}
70+
digits |= ((long) calculate10(digits)) << (9 << 2);
71+
assert (check10(digits));
72+
digits = Verify.getBitFlip(digits, 2, 40);
73+
if (check10(digits)) {
74+
System.out.println("Masked case: " + digits);
75+
}
76+
}
77+
}
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
package fault.injection.examples;
2+
3+
/*
4+
* Cyclic redundancy check algorithm
5+
* Assume the CRC algorithm is performed in GF(2)
6+
*/
7+
public class CRC {
8+
9+
int n; // divisor's length
10+
int[] d; // the divisor
11+
12+
CRC (String divisor) {
13+
n = divisor.length();
14+
d = new int[n];
15+
for (int i = 0; i < n; ++i) {
16+
assert (divisor.charAt(i) == '0' || divisor.charAt(i) == '1');
17+
d[i] = divisor.charAt(n-1-i) - '0';
18+
}
19+
}
20+
21+
// calculate the remainder of the given bit string
22+
public String remainder (String s) {
23+
// convert string to int array
24+
String padded = new String(s);
25+
for (int i = 0; i < n-1; ++i)
26+
padded += "0";
27+
int len = padded.length();
28+
int[] r = new int[len];
29+
for (int i = 0; i < len; ++i)
30+
r[i] = padded.charAt(len-1-i) - '0';
31+
for (int i = len-1; i >= n-1; --i) {
32+
if (r[i] == 1) {
33+
for (int j = 0; j < n; ++j)
34+
r[i-j] ^= d[n-1-j];
35+
}
36+
}
37+
String res = "";
38+
for (int i = n-2; i >= 0; --i)
39+
res += r[i];
40+
return res;
41+
}
42+
43+
// check the data integrity
44+
public boolean check (String s, String r) {
45+
if (s == null)
46+
return false;
47+
for (char c : s.toCharArray()) {
48+
if (c != '0' && c != '1')
49+
return false;
50+
}
51+
return remainder(s).equals(r);
52+
}
53+
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
package fault.injection.examples;
2+
3+
/*
4+
* International Standard Book Number (ISBN) error detection
5+
*/
6+
public class CheckISBN {
7+
// calculate the check digit for ISBN-10 based on the first 9 digits
8+
public static int calculate10 (int[] digits) {
9+
int s = 0, t = 0;
10+
for (int i = 0; i < 9; ++i) {
11+
t += digits[i];
12+
s += t;
13+
}
14+
return (11 - (s + t) % 11) % 11;
15+
}
16+
// ISBN-10 check
17+
public static boolean check10 (int[] digits) {
18+
if (digits == null || digits.length != 10)
19+
return false;
20+
for (int i = 0; i < 10; ++i) {
21+
if (digits[i] < 0 || digits[i] > 10 || (digits[i] == 10 && i != 9))
22+
return false;
23+
}
24+
return digits[9] == calculate10(digits);
25+
}
26+
27+
// calculate the check digit for ISBN-13 based on the first 12 digits
28+
public static int calculate13 (int[] digits) {
29+
int s = 0, t = 1;
30+
for (int i = 0; i < 12; ++i) {
31+
s += digits[i] * t;
32+
t = 4 - t;
33+
}
34+
return (10 - s % 10) % 10;
35+
}
36+
// ISBN-13 check
37+
public static boolean check13 (int[] digits) {
38+
if (digits == null || digits.length != 13)
39+
return false;
40+
for (int i = 0; i < 13; ++i) {
41+
if (digits[i] < 0 || digits[i] > 9)
42+
return false;
43+
}
44+
return digits[12] == calculate13(digits);
45+
}
46+
}
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
package fault.injection.examples;
2+
3+
import gov.nasa.jpf.vm.Verify;
4+
5+
/*
6+
* Cyclic redundancy check algorithm
7+
* Assume the CRC algorithm is performed in GF(2)
8+
* Assume the data length is less than 64 bits, and encode them in a variable of type long
9+
*/
10+
public class LongEncodedCRC {
11+
12+
int n; // divisor's length
13+
long d; // the divisor
14+
15+
LongEncodedCRC (String divisor) {
16+
n = divisor.length();
17+
d = 0;
18+
for (int i = 0; i < n; ++i) {
19+
assert (divisor.charAt(i) == '0' || divisor.charAt(i) == '1');
20+
d |= ((long) (divisor.charAt(n-1-i) - '0')) << i;
21+
}
22+
}
23+
24+
LongEncodedCRC (long _d) {
25+
d = _d;
26+
assert (d != 0);
27+
for (int i = 0; i < 64; ++i)
28+
if ((d >> i & 1) == 1) {
29+
n = i;
30+
}
31+
}
32+
33+
// calculate the remainder of the given bit string
34+
public long remainder (int len, long s) {
35+
long r = s << (n-1);
36+
len += n-1;
37+
for (int i = len-1; i >= n-1; --i) {
38+
if ((r >> i & 1) == 1) {
39+
r ^= d << (i-n+1);
40+
}
41+
}
42+
return r;
43+
}
44+
45+
// check the data integrity
46+
public boolean check (int len, long dataWithCheckBits) {
47+
long data = dataWithCheckBits >> (n-1);
48+
long checkBits = dataWithCheckBits & ((1 << (n-1)) - 1);
49+
return remainder(len, data) == checkBits;
50+
}
51+
52+
// check that bit flips in the data can be detected
53+
public static void main (String[] args) {
54+
LongEncodedCRC crc = new LongEncodedCRC("1011");
55+
int len = 14;
56+
long dataWithCheckBits = 0b11010011101100100l;
57+
assert (crc.check(len, dataWithCheckBits));
58+
long flippedData = Verify.getBitFlip(dataWithCheckBits, 2, 17);
59+
if (crc.check(len, flippedData)) {
60+
System.out.println("Masked case: " + flippedData);
61+
}
62+
}
63+
}

0 commit comments

Comments
 (0)