Skip to content

Commit

Permalink
Java grader: replace command line arguments with parameters file (#6990)
Browse files Browse the repository at this point in the history
* Java grader: replace command line arguments with parameters file

* Additional check for extra security

* Remove explicit note of exploit from student message
  • Loading branch information
jonatanschroeder committed Jan 26, 2023
1 parent ece0419 commit 2f263a8
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 8 deletions.
36 changes: 30 additions & 6 deletions graders/java/JUnitAutograder.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import org.junit.platform.engine.DiscoverySelector;
import org.junit.platform.engine.TestExecutionResult;
import org.junit.platform.engine.TestTag;
Expand All @@ -20,7 +21,9 @@
import javax.tools.ToolProvider;
import java.io.File;
import java.io.FileWriter;
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;
import java.io.StringWriter;
import java.util.*;

Expand Down Expand Up @@ -52,18 +55,38 @@ public JUnitAutograder() {

public static void main(String args[]) {

File paramsFile = new File("/grade/params/params.json");
JSONObject paramsObject = null;
try (Reader reader = new FileReader(paramsFile)) {
JSONParser paramsParser = new JSONParser();
paramsObject = (JSONObject) paramsParser.parse(reader);
} catch (Exception e) {
e.printStackTrace();
} finally {
paramsFile.delete();
}
if (paramsObject == null) {
System.err.println("Error parsing the parameter object.");
System.exit(0);
}
if (paramsFile.exists()) {
System.err.println("Error deleting the parameter file.");
System.exit(0);
}

JUnitAutograder autograder = new JUnitAutograder();
autograder.resultsFile = args[0];
autograder.testClasses = args[1].split("\\s");
if (!"".equals(args[2]))
autograder.message = "Compilation warnings:\n\n" + args[2];
autograder.resultsFile = (String) paramsObject.get("results_file");
autograder.testClasses = ((String) paramsObject.get("test_files")).split("\\s");
String compilationWarnings = (String) paramsObject.get("compile_output");
if (compilationWarnings != null && !"".equals(compilationWarnings))
autograder.message = "Compilation warnings:\n\n" + compilationWarnings;

try {
autograder.runTests();
} catch (UngradableException e) {
autograder.gradable = false;
} finally {
autograder.saveResults();
autograder.saveResults((String) paramsObject.get("signature"));
// Force exit to ensure any pending threads don't cause the autograder to hang
System.exit(0);
}
Expand Down Expand Up @@ -159,7 +182,7 @@ public synchronized void executionFinished(TestIdentifier test, TestExecutionRes
this.points += autograderTest.points;
}

private void saveResults() {
private void saveResults(String signature) {

double maxPoints = this.classTotals.entrySet().stream().mapToDouble(e -> {
if (e.getKey() != null) {
Expand Down Expand Up @@ -198,6 +221,7 @@ private void saveResults() {
results.put("message", this.message);
results.put("gradable", this.gradable);
results.put("tests", resultsTests);
results.put("signature", signature);

try (FileWriter writer = new FileWriter(this.resultsFile)) {
writer.write(results.toString());
Expand Down
21 changes: 19 additions & 2 deletions graders/java/autograder.sh
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ exception() {

mkdir -p /grade/results
mkdir -p /grade/classpath
mkdir -p /grade/params

cp -r /javagrader/*.class /javagrader/org /javagrader/libs/* /grade/classpath
cp -r /grade/tests/libs/* /grade/classpath 2> /dev/null
Expand All @@ -42,20 +43,36 @@ fi

RESULTS_TEMP_DIR=$(mktemp -d -p /grade/results)
RESULTS_TEMP_FILE="$RESULTS_TEMP_DIR/$RANDOM.json"
SIGNATURE=$(head -c 32 /dev/random | base64)

jq -n --arg results_file "$RESULTS_TEMP_FILE" \
--arg compile_output "$STUDENT_COMPILE_OUT" \
--arg test_files "$TEST_FILES" \
--arg signature "$SIGNATURE" \
'{results_file: $results_file, compile_output: $compile_output, test_files: $test_files, signature: $signature}' > /grade/params/params.json

chmod 700 /javagrader
chmod 711 /grade
chmod 700 /grade/*
chmod 711 /grade/results
chmod -R a+rX /grade/classpath
chmod 777 $RESULTS_TEMP_DIR
chmod 777 /grade/params
chmod 777 /grade/params/params.json

su - sbuser <<EOF
java -cp "$CLASSPATH" JUnitAutograder "$RESULTS_TEMP_FILE" "$TEST_FILES" "$STUDENT_COMPILE_OUT"
java -cp "$CLASSPATH" JUnitAutograder
EOF

if [ -f $RESULTS_TEMP_FILE ] ; then
mv $RESULTS_TEMP_FILE $RESULTS_FILE
RESULT_SIGNATURE=$(jq -r '.signature' $RESULTS_TEMP_FILE)
if [ "$RESULT_SIGNATURE" != "$SIGNATURE" ] ; then
echo Expected signature: $SIGNATURE
echo Provided signature: $RESULT_SIGNATURE
exception "Results did not contain correct signature. Please contact the instructor."
else
mv $RESULTS_TEMP_FILE $RESULTS_FILE
fi
else
exception "No grading results could be retrieved.
This usually means your program crashed before results could be saved.
Expand Down

0 comments on commit 2f263a8

Please sign in to comment.