将动态数组分配给变量(Pascal)时发生访问冲突

时间:2018-10-30 20:44:20

标签: pascal freepascal

将整数类型数组的动态数组分配给整数类型数组的变量时遇到访问错误。 PRGA函数返回一个整数数组。

有问题的行是:

keystream := PRGA(S, length(plaintext));

这是完整的代码:

program rc4;
uses
  sysutils, strutils;
type
  myArray = array[0..255] of integer;
  dynamicArray = array of integer;
  dynamicArrayString = array of string;
var
  S : myArray;
  keystream, cipher : dynamicArray;
  hexCipher : dynamicArrayString;
  key, plaintext, cipherString : string;
  i, sizeOfArray, sizeOfHexArray : integer;

function KSA(key : AnsiString) : myArray;
var
    i, j, key_length, temp, interJ: integer;
begin
    key_length := length(key);
    key_length := key_length;
  interJ := 0;
  j := 0;
  temp := 0;
  for i := 0 to 256 do
    S[i] := i;
  for i := 1 to 256 do  // allows access to first element of ansistring.
  begin                 // key[0] cannot be accessed
    interJ := i mod key_length; 
    if interJ = 0 then  // if interJ is 0, key[0] cannot be accessed
      interJ := 3;      // 3 mod 3 = 0
    j := ((j + S[i-1] + ord(key[interJ])) mod 256);
    temp := S[i-1];
    S[i-1] := S[j];
    S[j] := temp;
  end;
  KSA := S;
end;

function PRGA(S : myArray; n : integer) : dynamicArray;
var
  i, j, K, temp, sizeOfArray : integer;
  key : dynamicArray;
begin
  i := 0;
  j := 0;
  K := 0;
  temp := 0;
  sizeOfArray := n - 1;
  SetLength(key, sizeOfArray);
  while n > 0 do
  begin
    n := n - 1;
    i := (i + 1) mod 256;
    j := (j + S[i]) mod 256;
    temp := S[i];
    S[i] := S[j];
    S[j] := temp;
    K := S[(S[i] + S[j]) mod 256];
    key[i-1] := K;
  end;
  PRGA := key;
end;

begin
  sizeOfArray := 0;
  key := 'Key';
  plaintext := 'Plaintext';
  S := KSA(key);
  keystream := PRGA(S, length(plaintext));
  for i := 0 to (length(plaintext) - 1) do
  begin
    sizeOfArray := sizeOfArray + 1;
    SetLength(cipher, sizeOfArray);
    cipher[i] := ((keystream[i]) xor (ord(plaintext[i+1])));
  end;

  sizeOfHexArray := 0;
  for i := 0 to sizeOfArray - 1 do
  begin
    sizeOfHexArray := sizeOfHexArray + 1;
    SetLength(hexCipher, sizeOfHexArray);
    hexCipher[i] := IntToHex(cipher[i], 2);
  end;
  cipherString := '';
  for i := 0 to sizeOfHexArray - 1 do
  begin
    cipherString := cipherString + hexCipher[i];
  end;
  writeln(cipherString);
end.

我认为这是因为keystream变量的大小没有大小。但是,使用SetLength(keystream,length(plaintext))仍然会导致访问冲突。

1 个答案:

答案 0 :(得分:1)

有个好消息。您根本不需要hexCipher数组。只要做:

cipherString := '';
for I := 0 to High(cipher) do
  cipherString := cipherString + IntToHex(cipher[I], 2);

但是程序中存在很多一次性错误。看看KSA。我重写了一下:

function KSA(const key: AnsiString): myArray;
var
  i, j, key_length, temp: integer;
begin
  key_length := length(key);
  j := 0;
  for i := Low(S) to High(S) do
    S[i] := i;
  for i := Low(S) to High(S) do
  begin
    j := ((j + S[i] + ord(key[i mod key_length + 1])) mod 256);
    temp := S[i];
    S[i] := S[j];
    S[j] := temp;
  end;
  KSA := S;
end;

键是一个字符串,基于一个字符串,因此您只需 add 一个即可对其进行索引。不需要interJ。这整个1 to 256毫无意义。您想要更改数组S,所以请使用Low()High()(也许您必须启用“ mode delphi”才能使用它们,我不知道)。使用的mod 256确保索引j保持在0..255范围内。

此外,key[i mod key_length]对于从零开始的字符串也很好,但这是Pascal,而不是Python(引用您的previous question under a different name),因此,您只需将1添加到索引即可获取有效的AnsiString索引:key[i mod key_length + 1]。其他任何事情都会改变原始程序的逻辑。

一个例子:说您的密钥是'Secret',就像原始的Python例子一样。那么key_length6,因此i mod key_length0..5范围内。但是您的字符串具有索引1..6,因此只需添加1即可为字符串建立索引。

没有充分的理由在任何地方使用interJ := 3。那绝对没有道理。

在其余的代码中还有其他类似的问题(一次性错误索引)。我想您可以自己解决它们。