Skip to content

Commit 89c6648

Browse files
committed
Fixed Java magic byte detection and added test
1 parent 3c78fcf commit 89c6648

File tree

3 files changed

+31
-8
lines changed

3 files changed

+31
-8
lines changed

src/matchers/app.rs

+23-8
Original file line numberDiff line numberDiff line change
@@ -44,13 +44,23 @@ pub fn is_elf(buf: &[u8]) -> bool {
4444

4545
/// Returns whether a buffer is compiled Java bytecode.
4646
pub fn is_java(buf: &[u8]) -> bool {
47-
buf.len() >= 8
48-
&& buf[0] == 0x43
49-
&& buf[1] == 0x41
50-
&& buf[2] == 0x76
51-
&& buf[3] == 0x45
52-
&& ((buf[4] == 0x42 && buf[5] == 0x01 && buf[6] == 0x42 && buf[7] == 0x45)
53-
|| (buf[4] == 0x44 && buf[5] == 0x30 && buf[6] == 0x30 && buf[7] == 0x44))
47+
if buf.len() < 8 || [0xca, 0xfe, 0xba, 0xbe] != buf[0..4] {
48+
return false;
49+
}
50+
51+
//Checking the next 4 bytes are greater than or equal to 45 to distinguish from Mach-O binaries
52+
//Mach-O "Fat" binaries also use 0xCAFEBABE as magic bytes to start the file
53+
//Java are always Big Endian, after the magic bytes there are 2 bytes for the class file's
54+
//minor version and then 2 bytes for the major version
55+
//https://docs.oracle.com/javase/specs/jvms/se20/html/jvms-4.html
56+
let minor_major_bytes = [buf[4], buf[5], buf[6], buf[7]];
57+
if u32::from_be_bytes(minor_major_bytes) < 45 {
58+
//Java class files start at a major version of 45 and a minor of 0
59+
//So a value less than this shouldn't be a Java class file
60+
return false;
61+
}
62+
//For due dillegence confirm that the major bytes are greater than or equal to 45
63+
u16::from_be_bytes([buf[6], buf[7]]) >= 45
5464
}
5565

5666
/// Returns whether a buffer is LLVM Bitcode.
@@ -70,7 +80,12 @@ pub fn is_mach(buf: &[u8]) -> bool {
7080
match buf[0..4] {
7181
[width, 0xfa, 0xed, 0xfe] if width == 0xcf || width == 0xce => true,
7282
[0xfe, 0xed, 0xfa, width] if width == 0xcf || width == 0xce => true,
73-
[0xca, 0xfe, 0xba, 0xbe] => true,
83+
[0xca, 0xfe, 0xba, 0xbe] if buf.len() >= 8 => {
84+
//Checking the next 4 bytes are less than 45 to distinguish from Java class files
85+
//which also use 0xCAFEBABE as magic bytes
86+
//Fat Mach-O binaries are always Big Endian
87+
u32::from_be_bytes([buf[4], buf[5], buf[6], buf[7]]) < 45
88+
},
7489
_ => false,
7590
}
7691
}

testdata/sample.class

425 Bytes
Binary file not shown.

tests/app.rs

+8
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,14 @@ test_format!(
4242
"sample_mach_fat"
4343
);
4444

45+
test_format!(
46+
App,
47+
"application/java",
48+
"class",
49+
java,
50+
"sample.class"
51+
);
52+
4553
test_format!(App, "application/wasm", "wasm", wasm, "sample.wasm");
4654

4755
test_format!(App, "application/x-x509-ca-cert", "der", der, "sample.der");

0 commit comments

Comments
 (0)