这条怪线做什么用的?

时间:2018-06-06 09:47:30

标签: rust deobfuscation

使用Rust编译器的新测试完成pull request。它验证了一个奇怪的行可以编译:

fn main() {
    let val = !((|(..):(_,_),__@_|__)((&*"\\",'@')/**/,{})=={&[..=..][..];})//
    ;
    assert!(!val);
}

这条线到底是做什么的?

1 个答案:

答案 0 :(得分:23)

让我们分解吧!首先,我重新格式化了这条线,以增加“可读性”。

let val = !(
    (
        |(..): (_, _), __@_| __
    )(
        (
            &*"\\", 
            '@'
        ) /**/, 
        {}
    )
    ==
    {
        &[..=..][..];
    }
)//
;

let val =开头,以//<newline>;结尾。因此,它是let val = ⟨v⟩;形式的简单let-binding。我们来讨论一下⟨v⟩的作用:

  • 通过 not 运算符进行否定:!( ⟨_⟩ )
    • 通过==进行比较:⟨lhs⟩ == ⟨rhs⟩
      • ⟨lhs⟩ :关闭( ⟨closure⟩ )( ⟨args⟩ )的函数调用
        • ⟨closure⟩ :关闭定义|⟨first_param⟩, ⟨second_param⟩| ⟨body⟩
          • ⟨first_param⟩ (..): (_, _)。此参数具有类型注释(_, _),这意味着它是一个2元组。模式(通常情况下,您会找到一个名称)是(..),这意味着:一个元组,但忽略它的所有元素。
          • ⟨second_param⟩ __@_。这是一种通常从匹配绑定中获知的模式:name @ pattern。所以实际模式是_(它不绑定任何东西),并且值通过@绑定到名称__(两个下划线,这是一种有效的标识符)。
          • ⟨body⟩ __。这只是我们将第二个参数绑定到的标识符。因此,闭包基本上等同于|_, x| x
        • ⟨args⟩ :两个参数的列表,其中包含内嵌评论/**/⟨first_arg⟩/**/, ⟨second_arg⟩
          • ⟨first_arg⟩ (&*"\\", '@')。这只是一个2元组,其中第一个元素是包含反斜杠的字符串,第二个元素是char '@'。第一个元素的&*取消。
          • ⟨second_arg⟩ {}。这是一个类型为()的空块。所以作为第二个论点,一个单位被传递。
      • ⟨rhs⟩ :一个带有一个语句的支撑块:{ ⟨stmt⟩; }。请注意,这是一个带分号的语句。这意味着结果不会从块返回。相反,该块返回(),就像空块{}一样。
        • ⟨stmt⟩ :索引表达式{ &⟨collection⟩[⟨index⟩] }
          • ⟨collection⟩ [..=..]。这是一个包含一个元素的数组。元素为..= ..,其为RangeToInclusive,其中end范围为RangeFull ..
          • ⟨index⟩ ..。这只是RangeFull了。

总结:我们将调用闭包的结果与计算结果为()的支撑块进行比较。闭包基本上是|_, x| x,我们传递给它的第二个参数是{}(计算结果为()),因此整个闭包调用表达式的计算结果为()

这意味着整个事情等同于:

  • let val = !( () == () );,相当于:
  • let val = !( true );,相当于:
  • let val = false;