--- name: shmread signature: 'shmread ID, VAR, POS, SIZE' since: 5.0 status: documented categories: ["SysV IPC"] --- ```{index} single: shmread; Perl built-in ``` *[SysV IPC](../perlfunc-by-category)* # 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 ```perl 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 [`$!`](../perlvar) 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: ```perl shmread($id, my $buf, $pos, $size) or die "shmread(id=$id, pos=$pos, size=$size): $!"; ``` ## Global state it touches - [`$!`](../perlvar) — 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: ```perl 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: ```perl shmread($id, my $chunk, 256, 64) or die "shmread: $!"; # bytes 256..319 ``` Unpack a binary record straight out of shared memory: ```perl 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 # 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`](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`](shmget) (and, where applicable, by the segment's owner and current uid/gid). - **`VAR` need not be pre-sized.** Unlike [`sysread`](sysread), you do not `substr`-pad or preallocate `VAR` — `shmread` 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`](shmwrite) — the inverse: copy a string into a segment at a given offset - [`shmget`](shmget) — obtain or create the segment `ID` that `shmread` operates on - [`shmctl`](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`](sysread) — the file-descriptor analogue; same "bytes into a scalar" shape, different source - [`unpack`](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`](shmget)