-
Notifications
You must be signed in to change notification settings - Fork 0
Loaders
These functions are responsible for sourcing a script into the provided environment. They have two parameters where the first one is the file path of the script and the second one is the environment. These functions return a boolean value which controls the usage of default sourcing. A couple of loaders are provided below which are used in certain circumstances as examples.
loader <- function(file, envir) {
# Parse file instead of sourcing
parsed <- parse(file)
if(length(parsed) == 0) {
return()
}
# Execute lines one by one into the given environment
for (i in 1:length(parsed)) {
exp <- parsed[[i]]
object_call <- class(exp) == "name"
if(!object_call && length(exp) > 1) {
if(exp[[1]] == "setwd"){
next
} else if(exp[[1]] == '<-' && length(exp[[3]]) > 1 && exp[[3]][[1]] == "readdata") {
next
}
}
# Run the expression into the given environment
withTimeout(expr = exp, substitute = F, envir = envir, timeout = 1.5, onTimeout = "error")
}
# Consider the only injected when False normal source is tested as well
return(T)
}loader <- function(file, envir) {
# Parse file instead of sourcing
parsed <- parse(file)
if(length(parsed) == 0) {
return()
}
# Inject following lines as a start of each script in order to ensure same randomness
withTimeout(expr = parse(text="RNGversion(\"3.3.1\")"), substitute = F,
envir = envir, timeout = 1.5, onTimeout = "error")
withTimeout(expr = parse(text="set.seed(20200501)"), substitute = F,
envir = envir, timeout = 1.5, onTimeout = "error")
# Execute lines one by one into the given environment
for (i in 1:length(parsed)) {
exp <- parsed[[i]]
object_call <- class(exp) == "name"
if(!object_call && length(exp) > 1 && length(exp[[1]]) > 1) {
# Calling these functions by the scripts were forbidden since they contain RNG operations.
# If these were allowed, each call would change the random state therefore change the correct answer.
if(any(exp[[1]][[1]] == c("make_grade_matrix", "fundreturn", "fundreturn_aftertax")))
next
}
# Run the expression into the given environment
withTimeout(expr = exp, substitute = F, envir = envir, timeout = 1.5, onTimeout = "error")
}
# Consider the only injected when False normal source is tested as well
return(T)
}loader <- function(file, envir) {
# Parse file instead of sourcing
parsed <- parse(file)
if(length(parsed) == 0) {
return()
}
# Execute lines one by one into the given environment
for (i in 1:length(parsed)) {
exp <- parsed[[i]]
object_call <- class(exp) == "name"
if(!object_call) {
if(exp[[1]] == "setwd") {
next
}
# parameter of load function in scripts is changed to match with the location within the server
if(exp[[1]] == "load") {
exp[[2]] <- "path/to/data/folder/distance2.RData"
}
}
# Run the expression into the given environment
withTimeout(expr = exp, substitute = F, envir = envir, timeout = 1.5, onTimeout = "error")
}
# Consider the only injected when False normal source is tested as well
return(T)
}Here in the following example is used to change the value of a variable which should be defined at the beginning of the students to use later on for the given task. Normally, asking questions as a function and testing them with different arguments should suffice but here students have not learned about the functions yet. Therefore changing different inputs is only possible by altering the data by code injection.
loader <- function(file, envir) {
set.seed(2011400222)
hundred1 <- round(rnorm(20, 9, 0.5), 2)
names(hundred1) <- letters[sample(20)]
# Parse file instead of sourcing
parsed <- parse(file)
if(length(parsed) == 0) {
return()
}
# Execute lines one by one into the given environment
for (i in 1:length(parsed)) {
expression <- parsed[[i]]
object_call <- class(expression) == "name"
# Run the expression into the given environment
withTimeout(expr = expression, substitute = F, envir = envir, timeout = 1.5, onTimeout = "error")
# Change the variable as a test
if(!object_call && length(expression) > 1 && class(expression[[2]]) != "name") {
if(expression[[2]][[1]] == "names" && expression[[2]][[2]] == "hundred") {
assign("hundred", hundred1, envir = envir)
}
}
}
# Consider the only injected when False normal source is tested as well
return(T)
}