微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

模式中允许的功能集有限的 R 胶水?

如何解决模式中允许的功能集有限的 R 胶水?

我使用 glue() 来格式化字符串。理想情况下,我想让用户选择提供他自己的、可能复杂的格式模式。这些通常作为 yaml 配置文件的一部分分发,该文件还包含许多其他设置。

library(glue)
df <- tibble(a = c(70,80,90,4,5),conversionunit = c(60,60,1,1))
pattern <- "{a/conversionunit} minutes" # loaded from user's config file
df <- df %>% mutate(output = glue(pattern))

# more complex alternative
pattern <- "{round(a/conversionunit,digits=2)} minutes" # loaded from user's config file
df <- df %>% mutate(output = glue(pattern))

但是,由于 glue 语句可能会执行任意代码,因此存在安全风险。下面的例子当然是良性的。风险的产生是因为用户很可能在没有详细研究的情况下下载和使用复杂的配置文件,并且不法分子可能会分发邪恶的配置文件

pattern <- "{shell('echo 1',intern = TRUE)} {a}"
df <- df %>% mutate(output = glue(pattern))

我知道 glue_safe 但这比我想要的更严格。理想情况下,我想提供一个允许的功能列表

safe_fun <- list(`*` = `*`,`/` = `/`,"round" = round) %>% as.environment() # etc

并且只允许使用那些指定的。有没有办法做到这一点?

解决方法

定义保存数据和函数的环境并将其父级设置为 emptyenv()

library(glue)
library(tibble) # lst

safe_fun <- lst(`*`,`/`,round)
safe_env <- list2env(c(df,safe_fun),parent = emptyenv())

# test 1
glue("{a/conversionunit} minutes",.envir = safe_env)
## 1.16666666666667 minutes
## 1.33333333333333 minutes
## 1.5 minutes
## 4 minutes
## 5 minutes

# test 2
glue("{sqrt(a)/conversionunit} minutes",.envir = safe_env)
## Error in sqrt(a) : could not find function "sqrt"
,

以此previous answer为基础:

library(glue)
library(dplyr)

df <- tibble(a = c(70,80,90,4,5),conversionunit = c(60,60,1,1))

allowed <- c("/")

# Create new empty environment
safe_env <- new.env(parent = emptyenv())

# assign allowed functions & objects
lapply(allowed,function(f) assign(f,get(f),safe_env))
list2env(df,safe_env)

pattern <- "{a/conversionunit} minutes" # loaded from user's config file

df %>% mutate(output = glue(pattern,.envir=safe_env))
#> # A tibble: 5 x 3
#>       a conversionunit output                  
#>   <dbl>          <dbl> <glue>                  
#> 1    70             60 1.16666666666667 minutes
#> 2    80             60 1.33333333333333 minutes
#> 3    90             60 1.5 minutes             
#> 4     4              1 4 minutes               
#> 5     5              1 5 minutes


版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。