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
View Developer Edit
Welcome! If you don't have a Git account, you can't do anything here.
If you reported this bug, you can edit this bug over here.
(description)
Block user comment
Status: Assign to:
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