php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #31445 shmop_read() doesn't stop reading at NULL byte.
Submitted: 2005-01-07 22:46 UTC Modified: 2005-01-07 23:17 UTC
From: glideraerobatics at hotmail dot com Assigned:
Status: Not a bug Package: Unknown/Other Function
PHP Version: 5.0.3 OS: Linux
Private report: No CVE-ID: None
Welcome back! If you're the original bug submitter, here's where you can edit the bug or add additional notes.
If you forgot your password, you can retrieve your password here.
Password:
Status:
Package:
Bug Type:
Summary:
From: glideraerobatics at hotmail dot com
New email:
PHP Version: OS:

 

 [2005-01-07 22:46 UTC] glideraerobatics at hotmail dot com
Description:
------------
Either shmop_read() doesn't stop reading when it encouters a NULL byte, or shmop_write() doesn't write a NULL byte at the end of a string in the shared memory segment.


Reproduce code:
---------------
<?php
error_reporting(E_ALL | E_STRICT);

$key   = make_key('TEST');
$mode  = 'c';
$perms = 0644;
$size  = 80;


$shm_id = shmop_open($key, $mode, $perms, $size);
if (!$shm_id) {
  throw new Exception(sprintf('shmop_open(%x, "%s", 0%o, %u) failed.', $key, $mode, $perms, $size));
}
print 'Opened shm size: ' . shmop_size($shm_id) . "\n";


// Write long string.
$value = 'This is a kind of very long string.';
$result = shmop_write($shm_id, $value, 0);
printf("shmop_write(%x, '%s', 0) returned: %d\n", $shm_id, $value, $result);


// Read string back in.
$result = shmop_read($shm_id, 0, shmop_size($shm_id));
printf("shmop_read(%x, 0, %d) returned: '%s'\n", $shm_id, shmop_size($shm_id), $result);


// Write short string.
$value = 'This is short.';
$result = shmop_write($shm_id, $value, 0);
printf("shmop_write(%x, '%s', 0) returned: %d\n", $shm_id, $value, $result);


// Read string back in.
$result = shmop_read($shm_id, 0, shmop_size($shm_id));
printf("shmop_read(%x, 0, %d) returned: '%s'\n", $shm_id, shmop_size($shm_id), $result);


function make_key($value) {
  return ord(substr($value,0,1)) | (ord(substr($value,1,1))<<8) | (ord(substr($value,2,1))<<16) | (ord(substr($value,3,1)) << 24); //intel endian
}


?>

Expected result:
----------------
I expected the 1st shmop_read() call to return:
'This is a kind of very long string.'
....which it does, but I expected the 2nd shmop_read() call to return:
'This is short.'
...which it doesn't.

Actual result:
--------------
The 1st shmop_read() call returns:
'This is a kind of very long string.'
The 2nd shmop_read() call returns:
'This is short. of very long string.'
...which includes the trailing part of the first and longer string written with shmop_write().


Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2005-01-07 23:10 UTC] glideraerobatics at hotmail dot com
I made a work around for shmop_read() and shmop_write() to handle strings correctly. shmop_write() doesn't terminate written data with a null byte, and shmop_read() reads the whole memory segment. This is ok if your dealing with binary data so perhaps these functions shouldn't be considered bugged. Perhaps 2 similar functions should be introduced specially for handling strings (that's what most php programmers work with).

Here's the work around with 2 new custom functions for making a string null terminated and extracting a null terminated string from memory:

<?php
error_reporting(E_ALL | E_STRICT);

$key   = make_key('TEST');
$mode  = 'c';
$perms = 0644;
$size  = 80;


$shm_id = shmop_open($key, $mode, $perms, $size);
if (!$shm_id) {
  throw new Exception(sprintf('shmop_open(%x, "%s", 0%o, %u) failed.', $key, $mode, $perms, $size));
}
print 'Opened shm size: ' . shmop_size($shm_id) . "\n";


// Write long string.
$value = str_to_nts('This is a kind of very long string.');
$result = shmop_write($shm_id, $value, 0);
printf("shmop_write(%x, '%s', 0) returned: %d\n", $shm_id, $value, $result);


// Read string back in.
$result = str_from_mem(shmop_read($shm_id, 0, shmop_size($shm_id)));
printf("shmop_read(%x, 0, %d) returned: '%s'\n", $shm_id, shmop_size($shm_id), $result);


// Write short string.
$value = str_to_nts('This is short.');
$result = shmop_write($shm_id, $value, 0);
printf("shmop_write(%x, '%s', 0) returned: %d\n", $shm_id, $value, $result);


// Read string back in.
$result = str_from_mem(shmop_read($shm_id, 0, shmop_size($shm_id)));
printf("shmop_read(%x, 0, %d) returned: '%s'\n", $shm_id, shmop_size($shm_id), $result);


function make_key($value) {
  return ord(substr($value,0,1)) | (ord(substr($value,1,1))<<8) | (ord(substr($value,2,1))<<16) | (ord(substr($value,3,1)) << 24); //intel endian
}


function str_to_nts($value) {
  return "$value\0";
}


function str_from_mem(&$value) {
  $i = strpos($value, "\0");

  print "\n$i\n";

  if ($i === false) {
    return $value;
  }
  $result =  substr($value, 0, $i);
  return $result;
}


?>
 [2005-01-07 23:17 UTC] tony2001@php.net
Thank you for taking the time to write to us, but this is not
a bug. Please double-check the documentation available at
http://www.php.net/manual/ and the instructions on how to report
a bug at http://bugs.php.net/how-to-report.php

Use third parameter of shmop_read().
This is expected behaviour, 'cause one want to can store binary data in shared memory.
 
PHP Copyright © 2001-2025 The PHP Group
All rights reserved.
Last updated: Thu Jul 17 14:04:04 2025 UTC