与之前的提交比较代码提交?

4

用户在我的网站上提交代码(主要是Java)来解决简单的编程挑战,但将代码发送到服务器进行编译和执行有时需要超过10秒。

为了加快这个过程,我计划首先检查提交数据库,看看是否已经提交了等效的代码。我意识到这将导致随机方法始终返回相同的结果,但这并不重要。如果不运行代码,还可能引起其他潜在问题吗?

为了找到匹配项,在比较代码时,我会删除注释和空格。但是,同样的代码仍然可以用不同的方式编写,例如使用不同的变量名。有没有一种比较代码的方法可以找到更多等效的代码?


你更关心编译时间还是执行时间?根据编程语言,你可以存储已编译的字节码。 - SLaks
根据您的安全要求,这可能构成信息泄露漏洞;攻击者可以知道其他人是否提交了特定样本。这可能不是一个问题。 - SLaks
@SLaks,整个过程需要时间,所以我需要比较源代码而不是字节码。信息泄露在我的网站上不是问题。谢谢。 - Ari
你可以存储源代码到字节码的映射。 - SLaks
如果你想比较代码并检测简单的差异(例如,变量被重命名),你需要一个理解代码结构、重要性(例如,不是空格)以及如何仅基于语言结构检测差异的工具。 "diff" 不理解代码;它只理解行,因此效果不佳。您可以查看我们公司的 SmartDifferencer 源代码比较器,该工具使用完整的解析器,仅专注于结构上的差异。SO 不希望我发表链接;您必须查看我的个人资料。 - Ira Baxter
2个回答

2
您可以存储代码的SHA1哈希值以与以前的提交进行比较。您是正确的,不同的变量名称会给出不同的哈希值。试着通过一个缩小器或混淆器运行代码。这样,变量cat和dog都会像a1一样,然后您可以查看它们是否唯一。另外一种方法是将其编译成字节码,但那就太晚了。

与其分析源代码,何不加速编译呢?尝试使用自定义ClassLoader始终运行的servlet容器,并使用JDK tools.jar动态编译。您甚至可以通过AJAX REST提交代码并以同样的方式获取结果。

考虑Eclipse在后台如何编译您的文件。

此外,请考虑http://ideone.com如何实现他们的在线编译器。

请注意,允许随机代码执行是巨大的安全风险。您必须非常小心地对待黑客攻击。


谢谢,我会看看哈希表是否合适。实际上我正在使用Ideone,这就是有时候需要很长时间的原因! - Ari
我可以创建另一个表格,使用简化的代码和 add_index,这将允许快速查找。 - Ari
@Ari:如果存储不是问题,可以在混淆之前和之后都运行哈希。哈希速度更快,因此可以节省混淆的时间(如果幸运的话)。 - maaartinus

1
变量名称:
您可以编写代码来匹配一个文件中的变量名称与另一个文件中的变量名称,然后您可以将两个集合替换为一致的变量名称。
文件1: var1 += this(var1 - 1);
文件2: sum += this(sum - 1);
在读取文件1之后,您需要查找文件2在sum的位置上使用了哪个变量名称,然后使两个文件中的变量名称相同。
*注意,如果变量以类似的方式使用,则可能会得到错误的替换。这最有可能发生在变量被声明时。为了帮助减轻这种情况,您可以从文件底部开始搜索变量名称并向上工作。
简写:
强制使用{}和()括号包裹每个if/else/for/while等语句...
将“i+=…”这样的操作重写为“i=i+...”
函数:
在函数顺序不重要的情况下,您可以确保函数是等效的,然后忽略它们。

运算符优先级:
"3 + (2 * 4)"通常等同于"2 * 4 + 3"
解决这个问题的方法是确定每个操作的优先级,然后将其与另一组代码中具有相同优先级的操作匹配。一旦一组操作已经匹配,就可以用一个变量来代表它们。

例如:

(2+4) * 3 + (2+6) * 5 == someotherequation
//substitute most precedent: (2+4) and (2+6) for a and b  
... a * 3 + b * 5   
//substitute most precedent: (a*3) and (b*5) for c and d   
... c + d   
//substitute most precedent....   

这只是我能想到的一些方式。如果您按照这种方式操作,它将成为一个相当大的项目......特别是如果您正在使用多种语言。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接