WAF - 是时候跟正则表达式说再见WAF是时候跟正则表达式说再见 破见 weibo.com/u/5261507198 正则表达式不适合用于构建WAF 现有WAF的解决方案 如何构建未来的WAF Part 1 Part 2 Part 3 议题内容 Part 1 正则表达式不适合用于构建WAF 感性认识—误报和漏报难以平衡 尝试寻找有理证明 WAF自身安全 正则表达式 计算复杂度 计算复杂度 正则表达式DDOS攻击 非Regex DOS WAF防御能力 正则表达式DDOS攻击 提出一种正则表达式的DDOS攻击: 正则表达式的最坏时间复杂度大于等 于?(?2 ),该正则表达式可被DDOS 攻击 输入长度 (K) PCRE/PHP(ms) JAVA(ms) 1 0.5 32 2 23 53 4 111 142 8 458 DOS很难找到了 寻找能被DDOS的正则表达式 寻找最坏时间复杂度大于等于? ?? 的正则表达式 利用正则表达式匹配的回溯 正则表达式匹配原理:NFA 正则表达式:(a|b)*abb 对应的NFA 匹配算法需要尝试每一条路径,直到找到一条匹配路径。尝试所有路径失败则匹配失败。 • 尝试所有匹配路径 • 路径尝试失败,需要回溯 正则表达式DDOS原理 正则:A.*B0 码力 | 24 页 | 1.66 MB | 1 年前3
MoonBit月兔编程语言 现代编程思想 第二课 月兔开发与月兔中的表达式兔构建系统教程 7 ⽉兔中的表达式 8 ⼀个典型的⽉兔程序 1. //顶层函数定义 2. fn num_water_bottles(num_bottles: Int, num_exchange: Int) -> Int { 3. // 本地函数定义 4. fn consume(num_bottles, num_drunk) { 5. // 条件表达式 6. if num_bottles 9 基于表达式编程 为了写出正确的程序,我们需要知道程序是如何被运算的:我们需要建⽴计算模型 来理解程序的运算过程 ⽉兔程序可以通过⾯向值编程来描述 ⾯向值编程:定义是什么 我们写的⽉兔代码都是表达⼀个值的表达式 命令式编程⻛格:定义做什么 程序由修改程序状态的命令组成 创建名为x的变量 令x为5 令y指向x …… 10 类型、值与表达式 类型 值 运算 表达式 Int " + "MoonBit" Bool true false && || not() not(b1) || b2 每⼀个类型对应⼀个值的集合 每⼀个表达式由基于值的运算构成,并且可以简化为⼀个值(或已经是⼀个值) 可以使⽤括号来嵌套表达式 11 静态 vs 动态 �静态�指在程序运⾏之前的事物 �动态�指在程序运⾏之时的事物 ⽉兔拥有静态类型系统:在程序运⾏之前,编译器即会检查程序的类型是否定义良好0 码力 | 39 页 | 1.53 MB | 1 年前3
MoonBit月兔编程语言 现代编程思想 第三课 函数, 列表与递归 <类型> <表达式块> 定义的函数接⼝让其他使⽤者⽆需关注内部实现 1. fn one () -> Int { 2. 1 3. } 4. 5. fn add_char(ch: Char, str: String) -> String { 6. ch.to_string() + str 7. } 5 函数的应⽤与计算 当函数定义后,可以通过 <函数名>(<表达式>, <表达式>……) 的⽅式应⽤函数 one() add_char('m', "oonbit") 应⽤函数时,表达式与函数定义时的参数数量应当相同,且类型⼀⼀对应 这是错误的: add_char("oonbit", 'm') 计算应⽤函数的表达式时 从左到右计算定义了参数的表达式的值 替换函数内部参数 简化表达式 6 函数的应⽤与计算 1. fn add_char(ch: Char, str: String) add_char('m', "oonbit") 因为 Char::from_int(109) 'm' 'm'.to_string() + "oonbit" 替换表达式块中的标识符 "m" + "oonbit" 因为 m.to_string() "m" "moonbit"0 码力 | 42 页 | 587.59 KB | 1 年前3
MoonBit月兔编程语言 现代编程思想 第四课 多元组, 结构体,枚举类型 多元组,结构体与枚举类型 Hongbo Zhang 1 基础数据类型:多元组与结构体 2 回顾:多元组 多元组:固定⻓度的不同类型数据的集合 定义: (<表达式>, <表达式>, ...) 类型: (<表达式类型>, <表达式类型>, ...) 例如: 身份信息: ("Bob", 2023, 10, 24): (String, Int, Int, Int) 成员访问: <多元组> => Cons((hd, hd2), zip(tl, tl2)) 6. } 7. } 14 本地定义中的匹配 我们还可以在本地定义中利⽤模式进⾏匹配 let <模式> = <表达式> 此时会根据模式将表达式的值的⼦结构绑定到定义的标识符上,如: let (first, second) = (1, 2) // first == 1, second == 2 let Cons(1, x)0 码力 | 26 页 | 435.86 KB | 1 年前3
MoonBit月兔编程语言 现代编程思想 第十一课 案例:语法解析器与Tagless Final 现代编程思想 案例:语法解析器 Hongbo Zhang 1 语法解析器 案例⽬标 解析基于⾃然数的数学表达式: "(1+ 5) * 7 / 2" 转化为单词列表 LParen Value(1) Plus Value(5) Multiply Value(7) Divide Value(2) 转化为抽象语法树 Division(Multiply(Add(Value(1), Value(5)) 输出:单词流 例如: "12 +678" -> [ Value(12), Plus, Value(678) ] 通常可以通过有限状态⾃动机完成 ⼀般⽤领域特定语⾔定义后,由软件⾃动⽣成程序 算术表达式的词法定义 1. Number = %x30 / (%x31-39) *(%x30-39) 2. LParen = "(" 3. RParen = ")" 4. Plus = "+" 5. Minus = "-" 6. Multiply = "*" 7. Divide = "/" 8. Whitespace = " " 3 词法分析 算术表达式的词法定义 1. Number = %x30 / (%x31-39) *(%x30-39) 2. Plus = "+" 每⼀⾏对应⼀个匹配规则 "xxx" :匹配内容为xxx的字符串 a0 码力 | 25 页 | 400.29 KB | 1 年前3
MoonBit月兔编程语言 现代编程思想 第十二课 案例:自动微分 微分被应⽤于机器学习领域 利⽤梯度下降求局部极值 ⽜顿迭代法求函数解: 我们今天研究简单的函数组合 例: 12 微分 函数微分的⼏种⽅式 ⼿动微分:纯天然计算器 缺点:对于复杂表达式容易出错 数值微分: 缺点:计算机⽆法精准表达⼩数,且绝对值越⼤,越不精准 符号微分: Mul(Const(2), Var(1)) -> Const(2) 缺点:计算结果可能复杂;可能重复计算;难以直接利⽤语⾔原⽣控制流 缺点:对于复杂表达式容易出错 数值微分: 缺点:计算机⽆法精准表达⼩数,且绝对值越⼤,越不精准 符号微分: Mul(Const(2), Var(1)) -> Const(2) 缺点:计算结果可能复杂;可能重复计算;难以直接利⽤语⾔原⽣控制流 ⾃动微分:利⽤复合函数求导法则、由基本运算组合进⾏微分 分为前向微分和后向微分 14 符号微分 我们以符号微分定义表达式构建的⼀种语义 1 struct Backward { 2. value : Double // 当前节点计算值 3. backward : (Double) -> Unit // 对当前⼦表达式微分并累加 4. } 5. 6. fn Backward::var(value : Double, diff : Ref[Double]) -> Backward { 7. // 更新⼀条计算路径的偏微分0 码力 | 30 页 | 3.24 MB | 1 年前3
MoonBit月兔编程语言 现代编程思想 第六课 泛型与高阶函数
替换表达式中的标识符 let x: Int = add_two(2) add_two(2) plus_one(plus_one(2)) 替换表达式中的标识符 plus_one(2) + 1 替换表达式中的标识符 (2 + 1) + 1 替换表达式中的标识符0 码力 | 27 页 | 2.56 MB | 1 年前3
MoonBit月兔编程语言 现代编程思想 第五课 数据类型:树、二叉树、二叉搜索树、AVL树
Hongbo Zhang 1 数据结构:树 树 ⼆叉树 ⼆叉搜索树 ⼆叉平衡树 2 ⽣活中的树状图 ⽣活中有很多的数据的结构与⼀颗树相似 谱系图(⼜称,家族树) ⽂件结构 数学表达式 …… 3 树的逻辑结构 数据结构中,树是由有限个节点构成的具有层次关系的集合 节点是存储数据的结构,节点之间存在亲⼦关系:⽗节点和⼦节点 如果树不为空,则它拥有⼀个根节点:根节点没有⽗节点 = true || { abort("程序中⽌") } :因为 true || 任何值 均为真,因 此不会计算 || 右侧表达式 let y = false && { abort("程序中⽌") } :因为 false && 任何值 均为假, 因此不会计算 && 右侧表达式 树的遍历 value == target || dfs_search(target, left) || dfs_search(target0 码力 | 29 页 | 1015.26 KB | 1 年前3
MoonBit月兔编程语言 现代编程思想 第七课 命令式编程:命令,可变数据结构,循环 let x: Int = { 4. println("hello moonbit") // <-- 我们⾸先执⾏命令,进⾏输出 5. 1 + 1 // <-- 之后,我们以表达式块最后的值作为表达式块的值 6. } 7. let z: Int = square(x) // 4, 输出⼀次 8. } 5 命令与副作⽤ 我们不⼀定可以放⼼替换,因此会增⼤程序理解难度 1.0 码力 | 23 页 | 780.46 KB | 1 年前3
共 9 条
- 1













