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 underlyingshmat/memcpy/shmdterrors surface here).Taint flag on
VAR— set under-Tregardless of howVARwas 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#
VARis assigned to, not appended to. Any previous value is discarded. Use a fresh lexical if you need both old and new data.SIZEis exact, not a maximum.shmreaddoes not do short reads; requesting more bytes than the segment holds fromPOSonward fails rather than returning what fits.POSandSIZEmust lie within the segment declared atshmgettime.POS + SIZEpast the segment’s end fails withEINVAL.Zero
SIZEproduces an empty string inVARand succeeds, assumingPOSitself 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).VARneed not be pre-sized. Unlikesysread, you do notsubstr-pad or preallocateVAR—shmreadassigns the result directly.Taint. Under
-T,VARis 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 (typicallyENOSYS); portable code should guard with anevalor 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 offsetshmget— obtain or create the segmentIDthatshmreadoperates onshmctl— query segment metadata (IPC_STATfills in anshmid_dsyou can use to bound-checkPOS + SIZE) or remove the segment when donesysread— the file-descriptor analogue; same “bytes into a scalar” shape, different sourceunpack— turn the raw bytes returned inVARinto typed fieldsIPC::SysV— the module that suppliesIPC_PRIVATE,S_IRUSR, and the other constants you’ll pass toshmget