Source: libipc-shareable-perl
Version: 1.19-1
Severity: serious
Tags: ftbfs patch upstream
Justification: fails to build from source
Forwarded: https://github.com/stevieb9/ipc-shareable/issues/66
X-Debbugs-Cc: [email protected]


1.19-1 fails to build on ppc64el and ppc64, and builds everywhere else:

  https://buildd.debian.org/status/package.php?p=libipc-shareable-perl
https://buildd.debian.org/status/logs.php?pkg=libipc-shareable-perl&arch=ppc64el

  t/72-shm_segments.t  (Wstat: 6912 Tests: 47 Failed: 27)
  t/74-seg_map.t       (Wstat: 512  Tests: 12 Failed: 2)

lib/IPC/Shareable.pm unpacks struct shmid_ds at a hard-coded offset for
shm_segsz, assuming the asm-generic field order. PowerPC puts the three
time fields first, so on ppc64el/ppc64 the offset lands on shm_atime;
the oversized value makes the following shmread() fail and the segment
never reaches %segments. IPC/Shareable/SharedMem.pm has the same bug in
stat().

Reported upstream as #66, together with an alternative that drops the
offset tables entirely and reads the fields through IPC::SysV's XS
instead. Upstream has not replied yet, so the attached minimal fix is
what I would suggest for Debian; it is the least likely to conflict with
whichever route upstream takes.

Both solutions were built and tested on ppc64el under sbuild. No upstream reply yet.

Filed separately from #1142815, which is the unrelated t/47-seg_size.t
memory problem (upstream #65).

Kind regards,

    Edmund Lodewijks


--
Edmund Lodewijks <[email protected]>
TZ: UTC+2 / GMT+2

Description: shm_segments: use the PowerPC offset of shm_segsz on PowerPC
 PowerPC orders struct shmid_ds with the three time fields before shm_segsz;
 the generic layout puts shm_segsz first. The fixed offset therefore reads
 shm_atime on ppc64el and ppc64, and the oversized value makes the following
 shmread() fail, so the segment never reaches %segments. That fails
 t/72-shm_segments.t and t/74-seg_map.t.
 .
 Minimal alternative to portable-shmid_ds.patch; use one or the other.
Author: Edmund Lodewijks <[email protected]>
Forwarded: https://github.com/stevieb9/ipc-shareable/issues/66
Last-Update: 2026-08-28
---
--- a/lib/IPC/Shareable.pm
+++ b/lib/IPC/Shareable.pm
@@ -723,10 +723,16 @@
         my $stat_buf = '';
         shmctl($id, IPC_STAT, $stat_buf) or next;
 
+        # PowerPC orders struct shmid_ds with the three time fields before
+        # shm_segsz; everywhere else shm_segsz comes first, right after
+        # ipc_perm. Both ipc_perm layouts are 48 bytes, so shm_segsz sits at
+        # 72 rather than 48 on 64-bit, and at 76 rather than 36 on 32-bit.
+        my $ppc = $Config{archname} =~ /^(?:powerpc|ppc)/i;
+
         my ($segsz) = $^O eq 'linux'
             ? ( $Config{longsize} == 8
-            ? unpack('x[48] Q', $stat_buf)   # 64-bit Linux
-            : unpack('x[36] L', $stat_buf) ) # 32-bit Linux
+            ? unpack($ppc ? 'x[72] Q' : 'x[48] Q', $stat_buf)   # 64-bit Linux
+            : unpack($ppc ? 'x[76] L' : 'x[36] L', $stat_buf) ) # 32-bit Linux
             : $^O eq 'freebsd' && $Config{longsize} == 8
             ? unpack('x[32] Q', $stat_buf)   # 64-bit FreeBSD (key_t=long=8, ipc_perm=32)
             : $^O eq 'solaris'
Description: SharedMem::stat: use the PowerPC offsets of struct shmid_ds
 The per-OS offset table assumes the asm-generic field order, where shm_segsz
 follows ipc64_perm and the three time fields come after it. PowerPC puts the
 time fields first and shm_segsz after them, so segsz, atime, dtime and ctime
 are all read from the wrong place there. cpid, lpid and nattch are unaffected:
 both layouts are 48 bytes of ipc64_perm followed by four 8-byte fields, so
 those three keep their offsets.
 .
 Companion to powerpc-shmid_ds-offset.patch, which does the same for
 shm_segments(). No test currently catches this one: t/05-shm_stat.t asserts
 only segsz >= SHM_BUFSIZ, and the value misread on PowerPC is shm_atime, a
 timestamp far larger than SHM_BUFSIZ. The suite therefore passes without this
 patch, but stat() still reports nonsense on ppc64el and ppc64.
 .
 The 64-bit offsets match the kernel headers and qemu's target_structs.h, and
 are confirmed by a passing test suite on ppc64el under emulation. The 32-bit
 PowerPC arm is derived from the headers only and is untested; Debian's 32-bit
 powerpc is a ports architecture with no buildd coverage.
Author: Edmund Lodewijks <[email protected]>
Forwarded: https://github.com/stevieb9/ipc-shareable/issues/66
Last-Update: 2026-09-02
diff --git a/lib/IPC/Shareable/SharedMem.pm b/lib/IPC/Shareable/SharedMem.pm
index 4e6529e..3388ef4 100644
--- a/lib/IPC/Shareable/SharedMem.pm
+++ b/lib/IPC/Shareable/SharedMem.pm
@@ -191,14 +191,28 @@ sub stat {
     my %values;
 
     if ($^O eq 'linux') {
+        # PowerPC orders struct shmid_ds with the three time fields before
+        # shm_segsz; every other Linux architecture puts shm_segsz first,
+        # straight after ipc64_perm. Only that part of the struct differs.
+        my $ppc = $Config{archname} =~ /^(?:powerpc|ppc)/i;
+
         if ($Config{longsize} == 8) {
             # 64-bit Linux: ipc64_perm is 48 bytes.
             #   ipc64_perm: key(4) uid(4) gid(4) cuid(4) cgid(4) mode(4)
             #               seq(2) pad2(2) [4-byte align-pad] unused1(8) unused2(8)
             # shmid_ds: segsz(8) atime(8) dtime(8) ctime(8) cpid(4) lpid(4) nattch(8)
+            # PowerPC:  atime(8) dtime(8) ctime(8) segsz(8) cpid(4) lpid(4) nattch(8)
+            # (PowerPC's ipc64_perm is also 48 bytes: mode(4) seq(4) pad1(4)
+            #  where the generic one has mode(4) seq(2) pad2(2) plus padding.)
 
-            @values{qw(uid gid cuid cgid mode segsz atime dtime ctime cpid lpid nattch)}
-                = unpack('x[4] L L L L L x[24] Q q q q l l Q', $data);
+            if ($ppc) {
+                @values{qw(uid gid cuid cgid mode atime dtime ctime segsz cpid lpid nattch)}
+                    = unpack('x[4] L L L L L x[24] q q q Q l l Q', $data);
+            }
+            else {
+                @values{qw(uid gid cuid cgid mode segsz atime dtime ctime cpid lpid nattch)}
+                    = unpack('x[4] L L L L L x[24] Q q q q l l Q', $data);
+            }
         }
         else {
             # 32-bit Linux: ipc64_perm is 36 bytes (unsigned long = 4 bytes).
@@ -207,8 +221,18 @@ sub stat {
             # shmid_ds: segsz(4) atime(4) atime_nsec(4) dtime(4) dtime_nsec(4)
             #           ctime(4) ctime_nsec(4) cpid(4) lpid(4) nattch(4)
 
-            @values{qw(uid gid cuid cgid mode segsz atime dtime ctime cpid lpid nattch)}
-                = unpack('x[4] L L L L L x[12] L L x[4] L x[4] L x[4] l l L', $data);
+            # PowerPC 32-bit differs again: ipc64_perm is 48 bytes there, and
+            # each time field is preceded by its _high half, with one more
+            # pad word before segsz.
+
+            if ($ppc) {
+                @values{qw(uid gid cuid cgid mode atime dtime ctime segsz cpid lpid nattch)}
+                    = unpack('x[4] L L L L L x[24] x[4] L x[4] L x[4] L x[4] L l l L', $data);
+            }
+            else {
+                @values{qw(uid gid cuid cgid mode segsz atime dtime ctime cpid lpid nattch)}
+                    = unpack('x[4] L L L L L x[12] L L x[4] L x[4] L x[4] l l L', $data);
+            }
         }
     }
     elsif ($^O eq 'freebsd' && $Config{longsize} == 8) {

Attachment: OpenPGP_signature.asc
Description: OpenPGP digital signature

Reply via email to