Skip to content

Commit fdaf401

Browse files
committed
BREAKING: junit: Use relative resource paths with @DictionaryFile
The resource path is now interpreted relative to the class using the annotation, which is more idiomatic. This does require changing `com/example/Foo` to `/com/example/Foo` if an absolute path is desired.
1 parent 13a7c77 commit fdaf401

File tree

5 files changed

+22
-23
lines changed

5 files changed

+22
-23
lines changed

examples/junit/src/test/java/com/example/DictionaryFuzzTests.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ public void inlineTest(FuzzedDataProvider data)
4343
}
4444
}
4545

46-
@DictionaryFile(resourcePath = "com/example/test.dict")
46+
@DictionaryFile(resourcePath = "test.dict")
4747
@FuzzTest
4848
public void fileTest(FuzzedDataProvider data)
4949
throws NoSuchAlgorithmException, TestSuccessfulException {
@@ -55,8 +55,8 @@ public void fileTest(FuzzedDataProvider data)
5555
}
5656

5757
@DictionaryEntries(tokens = {"a_"})
58-
@DictionaryFile(resourcePath = "com/example/test2.dict")
59-
@DictionaryFile(resourcePath = "com/example/test3.dict")
58+
@DictionaryFile(resourcePath = "test2.dict")
59+
@DictionaryFile(resourcePath = "/com/example/test3.dict")
6060
@FuzzTest
6161
public void mixedTest(FuzzedDataProvider data)
6262
throws NoSuchAlgorithmException, TestSuccessfulException {
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
# test dictionary
22
"a_"
3-
"53Cr3T_"
3+
"53Cr\"3T_"
44
"fl4G"
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
"53Cr3T_"
1+
"53Cr\"3T_"

src/main/java/com/code_intelligence/jazzer/junit/DictionaryFile.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,13 @@
2323
import java.lang.annotation.Target;
2424

2525
/**
26-
* Defines a reference to a dictionary within the resources directory. The given {@code
27-
* resourcePath} must be an absolute path and must not have a leading {@code /}. These should follow
28-
* <a href="https://llvm.org/docs/LibFuzzer.html#dictionaries">libfuzzer's dictionary syntax</a>.
26+
* Attaches a dictionary file located in resources to a fuzz test. The file should follow <a
27+
* href="https://llvm.org/docs/LibFuzzer.html#dictionaries">libfuzzer's dictionary syntax</a>.
2928
*/
3029
@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE})
3130
@Retention(RetentionPolicy.RUNTIME)
3231
@Repeatable(DictionaryFiles.class)
3332
public @interface DictionaryFile {
33+
/** The resource path of the dictionary file. */
3434
String resourcePath();
3535
}

src/main/java/com/code_intelligence/jazzer/junit/FuzzerDictionary.java

Lines changed: 14 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,8 @@ static Optional<Path> createDictionaryFile(Method method) throws IOException {
6565
List<DictionaryFile> fileDictionaries =
6666
AnnotationSupport.findRepeatableAnnotations(method, DictionaryFile.class);
6767

68-
return FuzzerDictionary.createDictionaryFile(inlineDictionaries, fileDictionaries);
68+
return FuzzerDictionary.createDictionaryFile(
69+
inlineDictionaries, fileDictionaries, method.getDeclaringClass());
6970
}
7071

7172
/**
@@ -74,17 +75,20 @@ static Optional<Path> createDictionaryFile(Method method) throws IOException {
7475
*
7576
* @param inline list of {@link DictionaryEntries}
7677
* @param files list of {@link DictionaryFile}
78+
* @param declaringClass class containing the method with these annotations
7779
* @return Optional of dictionaryPath if created
7880
* @throws IOException
7981
*/
8082
private static Optional<Path> createDictionaryFile(
81-
List<DictionaryEntries> inline, List<DictionaryFile> files) throws IOException {
83+
List<DictionaryEntries> inline, List<DictionaryFile> files, Class<?> declaringClass)
84+
throws IOException {
8285
int sources = inline.size() + files.size();
8386
if (sources == 0) {
8487
return Optional.empty();
8588
}
8689

87-
Stream<String> joined = Stream.concat(getInlineTokens(inline), getFileTokens(files));
90+
Stream<String> joined =
91+
Stream.concat(getInlineTokens(inline), getFileTokens(files, declaringClass));
8892

8993
Path p = Files.createTempFile(DICTIONARY_PREFIX, DICTIONARY_SUFFIX);
9094
p.toFile().deleteOnExit();
@@ -120,26 +124,21 @@ private static Stream<String> getInlineTokens(List<DictionaryEntries> inline) {
120124
/**
121125
* Gets the individual lines from each of the specified dictionary files
122126
*
123-
* @param files List of {@link DictionaryFile} annotations indicating which files to use
127+
* @param files list of {@link DictionaryFile} annotations indicating which files to use
128+
* @param declaringClass class containing the method with these annotations
124129
* @return stream of all lines from each of the files
125130
*/
126-
private static Stream<String> getFileTokens(List<DictionaryFile> files) {
131+
private static Stream<String> getFileTokens(List<DictionaryFile> files, Class<?> declaringClass) {
127132
return files.stream()
128133
.map(DictionaryFile::resourcePath)
129-
.map(FuzzerDictionary::tokensFromResource)
134+
.map(resourcePath -> tokensFromResource(resourcePath, declaringClass))
130135
.flatMap(List::stream);
131136
}
132137

133-
private static List<String> tokensFromResource(String absoluteResourcePath) {
134-
if (absoluteResourcePath.startsWith("/")) {
135-
throw new IllegalArgumentException(
136-
String.format(
137-
"absolute resource path is must not have leading /: %s", absoluteResourcePath));
138-
}
139-
try (InputStream resourceFile =
140-
FuzzerDictionary.class.getClassLoader().getResourceAsStream(absoluteResourcePath)) {
138+
private static List<String> tokensFromResource(String resourcePath, Class<?> declaringClass) {
139+
try (InputStream resourceFile = declaringClass.getResourceAsStream(resourcePath)) {
141140
if (resourceFile == null) {
142-
throw new FileNotFoundException(absoluteResourcePath);
141+
throw new FileNotFoundException(resourcePath);
143142
}
144143
List<String> tokens;
145144
try (BufferedReader reader = new BufferedReader(new InputStreamReader(resourceFile))) {

0 commit comments

Comments
 (0)