FFI struct with flexible array member
オープン
まだ誰も着手していません。
Bug
Extension: ffi
Status: Verified
- 主要言語
- C
- スター
- 40.4k
- フォーク
- 8.2k
- 平均マージ
- 2日 15時間
- マージ済み PR(30日)
- 103
説明
Description
The following code:
<?php
echo 'Creating FFI struct...' . PHP_EOL;
$value = FFI::new('struct {
int32_t length;
char data[];
}');
echo 'Our struct is:' . PHP_EOL;
var_dump($value);
echo 'Our struct->data is:' . PHP_EOL;
var_dump($value->data);
echo 'Please keep in memory following will not work:' . PHP_EOL;
try {
$value->data = FFI::new('char[4]');
} catch (Throwable $t) {
echo ' - ' . $t->getMessage() . PHP_EOL;
}
echo PHP_EOL . 'Let\'s try something dirty:' . PHP_EOL;
var_dump($value->data[0]); // Well, it's ok, FFI is unsafe
var_dump($value->data[1000]); // No problem at all, we should carefully check boundaries
echo PHP_EOL . 'And even more dirtier:' . PHP_EOL;
$value->data[0] = 'a';
var_dump($value);
var_dump($value->data[0]);
echo 'I think I could broke something.' . PHP_EOL;
echo PHP_EOL . 'Let\'s fill our struct with value: ' . PHP_EOL;
FFI::memcpy($value, pack('V', 5), 4);
var_dump($value);
echo PHP_EOL . 'Will it work for array member? ' . PHP_EOL;
try {
FFI::memcpy($value, pack('V', 5) . 'aaaa', 8);
var_dump($value);
} catch (Throwable $t) {
echo ' - ' . $t->getMessage() . PHP_EOL;
echo 'Seems like it won\'t.' . PHP_EOL;
}
echo PHP_EOL . 'Maybe I can assign data directly to array member? ' . PHP_EOL;
try {
FFI::memcpy($value->data, 'aaaa', 4);
var_dump($value);
} catch (Throwable $t) {
echo ' - ' . $t->getMessage() . PHP_EOL;
echo 'Doesn\'t work either.' . PHP_EOL;
}
echo PHP_EOL . 'Or maybe I can assign to array member itself? ' . PHP_EOL;
try {
$value->data = FFI::new('char[4]');
var_dump($value);
} catch (Throwable) {
echo ' - ' . $t->getMessage() . PHP_EOL;
}
echo 'Do you remember last time we did this we got different error: ' . PHP_EOL;
echo ' - It was "Incompatible types when assigning to type \'char[]\' from type \'char[4]\'"' . PHP_EOL;
Resulted in this output:
Creating FFI struct...
Our struct is:
object(FFI\CData:struct <anonymous>)#1 (2) {
["length"]=>
int(0)
["data"]=>
object(FFI\CData:char[])#2 (0) {
}
}
Our struct->data is:
object(FFI\CData:char[])#2 (0) {
}
Please keep in memory following will not work:
- Incompatible types when assigning to type 'char[]' from type 'char[4]'
Let's try something dirty:
string(1) "▒"
string(1) "▒"
And even more dirtier:
object(FFI\CData:struct <anonymous>)#1 (2) {
["length"]=>
int(0)
["data"]=>
object(FFI\CData:char[])#2 (0) {
}
}
string(1) "a"
I think I could broke something.
Let's fill our struct with value:
object(FFI\CData:struct <anonymous>)#1 (2) {
["length"]=>
int(5)
["data"]=>
object(FFI\CData:char[])#2 (0) {
}
}
Will it work for array member?
- Attempt to write over data boundary
Seems like it won't.
Maybe I can assign data directly to array member?
- Attempt to write over data boundary
Doesn't work either.
Or maybe I can assign to array member itself?
- Attempt to write over data boundary
Do you remember last time we did this we got different error, it was:
- Incompatible types when assigning to type 'char[]' from type 'char[4]'
I did not expect something different, but it seems strange to me - flexible array members in structs are allowed, but I can't find the way how to use them.
PHP Version
PHP 8.1.1 (cli) NTS
Operating System
No response
コントリビューションガイド
はじめの一歩
- issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
- 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
- リポジトリをフォークし、ブランチを切って変更します。
- issue 番号を参照したプルリクエストを送ります。
調査の方向性
まず、提供された PHP 8.1.1 CLI 再現プログラムを実行し、境界エラーや代入の失敗を含め、報告された FFI のフレキシブル配列メンバーの動作を調査します。フレキシブル配列メンバーを使用するために想定されているサポート対象の方法を特定し、再現プログラムがその想定どおり一貫して動作することを確認します。
索引モデルが issue の本文から書いたものです。
評価
- 技術スタック
- c, php
- 領域
- backend
- issue の種類
- バグ
- 難易度
- 4/5
- 見積もり時間
- 3〜5日
- 活発さ
- 停滞
- 明瞭さ
- おおむね明確
- 初心者へのやさしさ
- 35/100