SysV IPC

shmread#

Copy bytes out of a System V shared memory segment into a Perl scalar.

shmread attaches to the shared memory segment identified by ID, reads SIZE bytes starting at byte offset POS, writes them into VAR, and detaches. VAR is assigned to as a whole — whatever it held before is replaced by exactly SIZE bytes of data. The variable is marked tainted under -T, because its contents came from outside the program.

Synopsis#

use IPC::SysV qw(IPC_PRIVATE S_IRUSR S_IWUSR);
my $id = shmget(IPC_PRIVATE, 4096, S_IRUSR | S_IWUSR)
    or die "shmget: $!";
shmread($id, my $buf, 0, 128)
    or die "shmread: $!";

What you get back#

Truthy on success, false on failure with $! set. On success VAR has been overwritten with exactly SIZE bytes; no short reads — either the whole range is copied in or the call fails. On failure VAR’s contents are unspecified; don’t rely on them.

Always check the return value. A bad ID, an out-of-range POS/ SIZE, or a segment the process lacks permission to attach all surface here as a false return:

shmread($id, my $buf, $pos, $size)
    or die "shmread(id=$id, pos=$pos, size=$size): $!";

Global state it touches#

  • $! — set on failure (any of the underlying shmat/memcpy/shmdt errors surface here).

  • Taint flag on VAR — set under -T regardless of how VAR was declared, because the bytes originate outside the program.

Examples#

Read a fixed-size record out of a segment:

use IPC::SysV qw(IPC_PRIVATE S_IRUSR S_IWUSR);
my $id = shmget(IPC_PRIVATE, 1024, S_IRUSR | S_IWUSR) or die "shmget: $!";
shmwrite($id, "hello, world", 0, 12)                  or die "shmwrite: $!";
shmread($id, my $buf, 0, 12)                          or die "shmread: $!";
print $buf, "\n";                                     # hello, world

Read at an offset. POS and SIZE are in bytes, not elements — the segment has no notion of records:

shmread($id, my $chunk, 256, 64)
    or die "shmread: $!";                             # bytes 256..319

Unpack a binary record straight out of shared memory:

shmread($id, my $raw, 0, 16) or die "shmread: $!";
my ($magic, $len, $flags) = unpack "a4 N N", $raw;

Reading tainted data under -T. The assignment is guaranteed to produce a tainted scalar even if VAR already held an untainted value:

# perl -T
shmread($id, my $buf, 0, $n) or die "shmread: $!";
# $buf is tainted; untaint via a regex match before using
# it in a sensitive context.

Edge cases#

  • VAR is assigned to, not appended to. Any previous value is discarded. Use a fresh lexical if you need both old and new data.

  • SIZE is exact, not a maximum. shmread does not do short reads; requesting more bytes than the segment holds from POS onward fails rather than returning what fits.

  • POS and SIZE must lie within the segment declared at shmget time. POS + SIZE past the segment’s end fails with EINVAL.

  • Zero SIZE produces an empty string in VAR and succeeds, assuming POS itself is valid.

  • Permissions. The calling process must have read permission on the segment, as dictated by the mode bits passed to shmget (and, where applicable, by the segment’s owner and current uid/gid).

  • VAR need not be pre-sized. Unlike sysread, you do not substr-pad or preallocate VARshmread assigns the result directly.

  • Taint. Under -T, VAR is tainted on success regardless of what it held before. Launder through a capture-group match ($data =~ /\A(.*)\z/s and $data = $1) only once you’ve validated the bytes are safe for the sensitive operation you’re about to perform.

  • Not every platform has SysV IPC. On systems without shmat(2) the call fails at runtime (typically ENOSYS); portable code should guard with an eval or feature probe.

Differences from upstream#

Fully compatible with upstream Perl 5.42.

See also#

  • shmwrite — the inverse: copy a string into a segment at a given offset

  • shmget — obtain or create the segment ID that shmread operates on

  • shmctl — query segment metadata (IPC_STAT fills in an shmid_ds you can use to bound-check POS + SIZE) or remove the segment when done

  • sysread — the file-descriptor analogue; same “bytes into a scalar” shape, different source

  • unpack — turn the raw bytes returned in VAR into typed fields

  • IPC::SysV — the module that supplies IPC_PRIVATE, S_IRUSR, and the other constants you’ll pass to shmget