c - Ada 中的无约束数组可以安全使用吗?
问题描述
我正在阅读 Ada 中的数组类型,发现有趣的是,与 C++ 不同,该语言允许它们的大小在编译时是未知的。我不确定它们是如何实现的,所以我写了一个小测试:
with Ada.Text_IO; use Ada.Text_IO;
with Ada.Command_Line; use Ada.Command_Line;
procedure Main is
type Data is array (1 .. 131_072) of Integer;
type Vector is array (Positive range <>) of Data;
Sequence : Vector (1 .. Argument_Count);
begin
for I in Sequence'Range loop
Sequence (I) := (others => I);
Put (Integer'Image (Sequence (I)(1)));
end loop;
end Main;
然后尝试使用可变长度数组在 C 中复制此代码:
#include <stdio.h>
struct data {
int x[131072];
};
int main(int argc, char** argv) {
(void)argv;
struct data sequence[argc - 1];
for (int i = 0; i < argc - 1; i++) {
for (int j = 0; j < 131072; j++)
sequence[i].x[j] = i;
printf("%i ", sequence[i].x[1]);
}
}
gnatmake -gnato -fstack-check -gnat2012 -gnata -O3 main.adb -o main
我用和编译gcc -O3 -Wall -Werror -Wextra -pedantic cmain.c -o cmain
。运行程序后,当给定 16 个或更多参数时,两者都失败了 - 不同之处在于,cmain
只是发生了段错误,而main
最终引发了“STORAGE_ERROR:堆栈溢出或错误的内存访问”。
由于 VLA 和无约束数组似乎(至少在表面上)都以类似的方式实现,并且前者被广泛认为在几乎所有情况下都不能安全使用,所以使用后者是否安全?
解决方案
Ada 中的无约束数组类型本身并不是不安全的;不安全或至少可能导致异常的是使用未经检查的输入值(例如 Argument_Count)来创建该大小的数组对象。如果您这样做,并且没有异常处理程序,则攻击者可以使您的程序因未处理的异常而中止,如您的示例所示。
请注意,不受约束的数组类型在 Ada 中以两种方式使用:
- 如您的示例所示,创建动态确定大小的数组对象。
- 将各种大小的数组作为参数传递给子程序,即使实际的数组对象具有静态定义的大小。
第二种使用(参数)当然是完全安全的,参数的实际边界可以照常通过 A'First、A'Last、A'Range、A'Length 访问。
推荐阅读
- graph - 用于查找图的根节点的 Cypher 查询
- scala - 在 Scala 中将数据帧转换为 Map 时出现编译器错误
- javascript - Angular 7 动画导致 webkit 浏览器上的 z-index 重叠问题
- python - 分区(如果适用)
- azure-devops - Azure DevOps 用户故事未显示在“就绪”列中
- radio-button - 如何在角度材料6中隐藏单选按钮
- play-billing-library - 使用 com.android.billingclient.api 使用开发人员有效负载进行订阅购买
- .net - 如何在 Elasticsearch.Net 中进行查询字符串查询?
- angular - 找不到“权限”管道?
- java - Spring Boot 中的并发