php / php/php-src

FFI struct with flexible array member

Open
#7,949 3 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Bug Extension: ffi Status: Verified
Dominant language
C
Stars
40.4k
Forks
8.1k
Avg merge
2d 13h
Merged PRs (30d)
96

Description

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

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by running the supplied PHP 8.1.1 CLI reproducer and inspect the reported behavior of FFI flexible array members, including the boundary errors and assignment failures. Determine the intended supported way to use a flexible array member and verify that the reproducer behaves consistently with that expectation.

Written by the indexing model from the issue text.

Assessment

Tech stack
c, php
Domain
backend
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.