php / php/php-src

FFI struct with flexible array member

オープン
#7,949 コメント 3 件 リアクション 0 件 担当者 0 名 GitHub で見る

まだ誰も着手していません。

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

コントリビューションガイド

コントリビューションガイドを開く

はじめの一歩

  1. issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
  2. 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
  3. リポジトリをフォークし、ブランチを切って変更します。
  4. issue 番号を参照したプルリクエストを送ります。

調査の方向性

まず、提供された PHP 8.1.1 CLI 再現プログラムを実行し、境界エラーや代入の失敗を含め、報告された FFI のフレキシブル配列メンバーの動作を調査します。フレキシブル配列メンバーを使用するために想定されているサポート対象の方法を特定し、再現プログラムがその想定どおり一貫して動作することを確認します。

索引モデルが issue の本文から書いたものです。

評価

技術スタック
c, php
領域
backend
issue の種類
バグ
難易度
4/5
見積もり時間
3〜5日
活発さ
停滞
明瞭さ
おおむね明確
初心者へのやさしさ
35/100

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。