Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package perl-Sys-Mmap for openSUSE:Factory 
checked in at 2026-06-09 14:26:10
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/perl-Sys-Mmap (Old)
 and      /work/SRC/openSUSE:Factory/.perl-Sys-Mmap.new.2375 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "perl-Sys-Mmap"

Tue Jun  9 14:26:10 2026 rev:2 rq:1358069 version:0.210.0

Changes:
--------
--- /work/SRC/openSUSE:Factory/perl-Sys-Mmap/perl-Sys-Mmap.changes      
2024-09-04 13:26:32.878595280 +0200
+++ /work/SRC/openSUSE:Factory/.perl-Sys-Mmap.new.2375/perl-Sys-Mmap.changes    
2026-06-09 14:28:41.817399566 +0200
@@ -1,0 +2,27 @@
+Mon Mar 23 06:24:02 UTC 2026 - Tina Müller <[email protected]>
+
+- updated to 0.210.0 (0.21)
+   see /usr/share/doc/packages/perl-Sys-Mmap/Changes
+
+  Todd Rinaldo, Mar 22 2026 v0.21
+  Bug Fixes:
+  * Fix segfault with non-zero offset in mmap. When mmap() was called with
+    a non-zero offset, Perl's sv_clear would try to Safefree() the mmap'd
+    pointer on scope exit, causing a crash. Now uses Perl's magic system to
+    store unmap metadata safely. GH #1, PR #12
+  * Fix len=0 with offset inferring wrong mapped size. When mmap() was
+    called with len=0 and a non-zero offset, the length was inferred as the
+    full file size rather than file_size - offset, causing the mapping to
+    extend past the end of the file. PR #14
+  * Resolve tied interface DESTROY munmap failures. DESTROY receives a
+    blessed reference, not the mmap'd SV itself. Without dereferencing,
+    the magic lookup failed and tried to munmap a garbage pointer. PR #16
+  Improvements:
+  * Document len=0 with offset behavior and caveats in POD. Clarify that
+    len=0 with offset infers remaining file size, document the
+    offset-beyond-EOF error, and add caveat about page alignment. PR #15
+  Maintenance:
+  * Modernize CI: consolidate separate linux.yml and macos.yml into a
+    unified testsuite.yml with updated actions and containers. PR #13
+
+-------------------------------------------------------------------

Old:
----
  Sys-Mmap-0.20.tar.gz

New:
----
  README.md
  Sys-Mmap-0.21.tar.gz
  _scmsync.obsinfo
  build.specials.obscpio

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ perl-Sys-Mmap.spec ++++++
--- /var/tmp/diff_new_pack.Uue1dT/_old  2026-06-09 14:28:44.145496192 +0200
+++ /var/tmp/diff_new_pack.Uue1dT/_new  2026-06-09 14:28:44.145496192 +0200
@@ -1,7 +1,7 @@
 #
 # spec file for package perl-Sys-Mmap
 #
-# Copyright (c) 2024 SUSE LLC
+# Copyright (c) 2026 SUSE LLC and contributors
 #
 # All modifications and additions to the file contributed by third parties
 # remain the property of their copyright owners, unless otherwise agreed
@@ -18,15 +18,16 @@
 
 %define cpan_name Sys-Mmap
 Name:           perl-Sys-Mmap
-Version:        0.200.0
+Version:        0.210.0
 Release:        0
-# 0.20 -> normalize -> 0.200.0
-%define cpan_version 0.20
+# 0.21 -> normalize -> 0.210.0
+%define cpan_version 0.21
 License:        Artistic-1.0 OR GPL-1.0-or-later
 Summary:        Uses mmap to map in a file as a Perl variable
 URL:            https://metacpan.org/release/%{cpan_name}
 Source0:        
https://cpan.metacpan.org/authors/id/T/TO/TODDR/%{cpan_name}-%{cpan_version}.tar.gz
 Source1:        cpanspec.yml
+Source100:      README.md
 BuildRequires:  perl
 BuildRequires:  perl-macros
 Provides:       perl(Sys::Mmap) = %{version}
@@ -50,105 +51,8 @@
 area, and sparse memory usage is handled optimally on most modern UNIX
 implementations.
 
-Using the 'new()' method provides a 'tie()''d interface to 'mmap()' that
-allows you to use the variable as a normal variable. If a filename is
-provided, the file is opened and mapped in. If the file is smaller than the
-length provided, the file is grown to that length. If no filename is
-provided, anonymous shared inheritable memory is used. Assigning to the
-variable will replace a section in the file corresponding to the length of
-the variable, leaving the remainder of the file intact and unmodified.
-Using 'substr()' allows you to access the file at an offset, and does not
-place any requirements on the length argument to 'substr()' or the length
-of the variable being inserted, provided it does not exceed the length of
-the memory region. This protects you from the pathological cases involved
-in using 'mmap()' directly, documented below.
-
-When calling 'mmap()' or 'hardwire()' directly, you need to be careful how
-you use the variable. Some programming constructs may create copies of a
-string which, while unimportant for smallish strings, are far less welcome
-if you're mapping in a file which is a few gigabytes big. If you use
-'PROT_WRITE' and attempt to write to the file via the variable you need to
-be even more careful. One of the few ways in which you can safely write to
-the string in-place is by using 'substr()' as an lvalue and ensuring that
-the part of the string that you replace is exactly the same length. Other
-functions will allocate other storage for the variable, and it will no
-longer overlay the mapped in file.
-
-* Sys::Mmap->new( 'VARIABLE', 'LENGTH', 'OPTIONALFILENAME' )
-
-Maps 'LENGTH' bytes of (the contents of) 'OPTIONALFILENAME' if
-'OPTIONALFILENAME' is provided, otherwise uses anonymous, shared
-inheritable memory. This memory region is inherited by any 'fork()'ed
-children. 'VARIABLE' will now refer to the contents of that file. Any
-change to 'VARIABLE' will make an identical change to the file. If 'LENGTH'
-is zero and a file is specified, the current length of the file will be
-used. If 'LENGTH' is larger then the file, and 'OPTIONALFILENAME' is
-provided, the file is grown to that length before being mapped. This is the
-preferred interface, as it requires much less caution in handling the
-variable. 'VARIABLE' will be tied into the "Sys::Mmap" package, and
-'mmap()' will be called for you.
-
-Assigning to 'VARIABLE' will overwrite the beginning of the file for a
-length of the value being assigned in. The rest of the file or memory
-region after that point will be left intact. You may use 'substr()' to
-assign at a given position:
-
-    substr(VARIABLE, POSITION, LENGTH) = NEWVALUE
-
-* mmap(VARIABLE, LENGTH, PROTECTION, FLAGS, FILEHANDLE, OFFSET)
-
-Maps 'LENGTH' bytes of (the underlying contents of) 'FILEHANDLE' into your
-address space, starting at offset 'OFFSET' and makes 'VARIABLE' refer to
-that memory. The 'OFFSET' argument can be omitted in which case it defaults
-to zero. The 'LENGTH' argument can be zero in which case a stat is done on
-'FILEHANDLE' and the size of the underlying file is used instead.
-
-The 'PROTECTION' argument should be some ORed combination of the constants
-'PROT_READ', 'PROT_WRITE' and 'PROT_EXEC', or else 'PROT_NONE'. The
-constants 'PROT_EXEC' and 'PROT_NONE' are unlikely to be useful here but
-are included for completeness.
-
-The 'FLAGS' argument must include either 'MAP_SHARED' or 'MAP_PRIVATE' (the
-latter is unlikely to be useful here). If your platform supports it, you
-may also use 'MAP_ANON' or 'MAP_ANONYMOUS'. If your platform supplies
-'MAP_FILE' as a non-zero constant (necessarily non-POSIX) then you should
-also include that in 'FLAGS'. POSIX.1b does not specify 'MAP_FILE' as a
-'FLAG' argument and most if not all versions of Unix have 'MAP_FILE' as
-zero.
-
-mmap returns 'undef' on failure, and the address in memory where the
-variable was mapped to on success.
-
-* munmap(VARIABLE)
-
-Unmaps the part of your address space which was previously mapped in with a
-call to 'mmap(VARIABLE, ...)' and makes VARIABLE become undefined.
-
-munmap returns 1 on success and undef on failure.
-
-* hardwire(VARIABLE, ADDRESS, LENGTH)
-
-Specifies the address in memory of a variable, possibly within a region
-you've 'mmap()'ed another variable to. You must use the same precautions to
-keep the variable from being reallocated, and use 'substr()' with an exact
-length. If you 'munmap()' a region that a 'hardwire()'ed variable lives in,
-the 'hardwire()'ed variable will not automatically be 'undef'ed. You must
-do this manually.
-
-* Constants
-
-The Sys::Mmap module exports the following constants into your namespace:
-
-    MAP_SHARED MAP_PRIVATE MAP_ANON MAP_ANONYMOUS MAP_FILE
-    MAP_NORESERVE MAP_POPULATE
-    MAP_HUGETLB MAP_HUGE_2MB MAP_HUGE_1GB
-    PROT_EXEC PROT_NONE PROT_READ PROT_WRITE
-
-Of the constants beginning with 'MAP_', only 'MAP_SHARED' and 'MAP_PRIVATE'
-are defined in POSIX.1b and only 'MAP_SHARED' is likely to be useful.
-
 %prep
-%autosetup  -n %{cpan_name}-%{cpan_version}
+%autosetup -n %{cpan_name}-%{cpan_version} -p1
 
 %build
 perl Makefile.PL INSTALLDIRS=vendor OPTIMIZE="%{optflags}"

++++++ README.md ++++++

## Build Results

Current state of perl in openSUSE:Factory is

![Factory build 
results](https://br.opensuse.org/status/openSUSE:Factory/perl-Sys-Mmap/standard)

The current state of perl in the devel project build (devel:languages:perl)

![Devel project build 
results](https://br.opensuse.org/status/devel:languages:perl/perl-Sys-Mmap)



++++++ Sys-Mmap-0.20.tar.gz -> Sys-Mmap-0.21.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Sys-Mmap-0.20/Changes new/Sys-Mmap-0.21/Changes
--- old/Sys-Mmap-0.20/Changes   2020-02-13 19:34:40.000000000 +0100
+++ new/Sys-Mmap-0.21/Changes   2026-03-22 22:33:29.000000000 +0100
@@ -1,3 +1,27 @@
+Todd Rinaldo, Mar 22 2026 v0.21
+
+Bug Fixes:
+* Fix segfault with non-zero offset in mmap. When mmap() was called with
+  a non-zero offset, Perl's sv_clear would try to Safefree() the mmap'd
+  pointer on scope exit, causing a crash. Now uses Perl's magic system to
+  store unmap metadata safely. GH #1, PR #12
+* Fix len=0 with offset inferring wrong mapped size. When mmap() was
+  called with len=0 and a non-zero offset, the length was inferred as the
+  full file size rather than file_size - offset, causing the mapping to
+  extend past the end of the file. PR #14
+* Resolve tied interface DESTROY munmap failures. DESTROY receives a
+  blessed reference, not the mmap'd SV itself. Without dereferencing,
+  the magic lookup failed and tried to munmap a garbage pointer. PR #16
+
+Improvements:
+* Document len=0 with offset behavior and caveats in POD. Clarify that
+  len=0 with offset infers remaining file size, document the
+  offset-beyond-EOF error, and add caveat about page alignment. PR #15
+
+Maintenance:
+* Modernize CI: consolidate separate linux.yml and macos.yml into a
+  unified testsuite.yml with updated actions and containers. PR #13
+
 Todd Rinaldo, Feb 13 2020 v0.20
 * Add use warnings to improve kwalitee
 * Spelling error in manpage
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Sys-Mmap-0.20/MANIFEST new/Sys-Mmap-0.21/MANIFEST
--- old/Sys-Mmap-0.20/MANIFEST  2020-02-13 19:35:17.000000000 +0100
+++ new/Sys-Mmap-0.21/MANIFEST  2026-03-22 22:35:05.000000000 +0100
@@ -7,8 +7,10 @@
 Mmap.pm
 Mmap.xs
 README
+t/comprehensive.t
 t/mmap.t
 t/munmap_errors.t
+t/offset.t
 xt/author/pod.t
 META.yml                                 Module YAML meta-data (added by 
MakeMaker)
 META.json                                Module JSON meta-data (added by 
MakeMaker)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Sys-Mmap-0.20/MANIFEST.SKIP 
new/Sys-Mmap-0.21/MANIFEST.SKIP
--- old/Sys-Mmap-0.20/MANIFEST.SKIP     2020-02-13 19:34:15.000000000 +0100
+++ new/Sys-Mmap-0.21/MANIFEST.SKIP     2026-03-22 22:34:42.000000000 +0100
@@ -1,6 +1,4 @@
-^.github/
-^.git/.*
-^MYMETA.*
-^MANIFEST.bak
-^Makefile
-^.gitignore
+^.git
+^MYMETA\.*
+^MANIFEST\.bak$
+^Makefile$
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Sys-Mmap-0.20/META.json new/Sys-Mmap-0.21/META.json
--- old/Sys-Mmap-0.20/META.json 2020-02-13 19:35:17.000000000 +0100
+++ new/Sys-Mmap-0.21/META.json 2026-03-22 22:35:05.000000000 +0100
@@ -4,7 +4,7 @@
       "Scott Walters <[email protected]>"
    ],
    "dynamic_config" : 1,
-   "generated_by" : "ExtUtils::MakeMaker version 7.34, CPAN::Meta::Converter 
version 2.150010",
+   "generated_by" : "ExtUtils::MakeMaker version 7.76, CPAN::Meta::Converter 
version 2.150010",
    "license" : [
       "perl_5"
    ],
@@ -52,6 +52,6 @@
          "url" : "http://github.com/toddr/Sys-Mmap/tree/master";
       }
    },
-   "version" : "0.20",
-   "x_serialization_backend" : "JSON::PP version 4.02"
+   "version" : "0.21",
+   "x_serialization_backend" : "JSON::PP version 4.16"
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Sys-Mmap-0.20/META.yml new/Sys-Mmap-0.21/META.yml
--- old/Sys-Mmap-0.20/META.yml  2020-02-13 19:35:17.000000000 +0100
+++ new/Sys-Mmap-0.21/META.yml  2026-03-22 22:35:05.000000000 +0100
@@ -9,7 +9,7 @@
 configure_requires:
   ExtUtils::MakeMaker: '0'
 dynamic_config: 1
-generated_by: 'ExtUtils::MakeMaker version 7.34, CPAN::Meta::Converter version 
2.150010'
+generated_by: 'ExtUtils::MakeMaker version 7.76, CPAN::Meta::Converter version 
2.150010'
 license: perl
 meta-spec:
   url: http://module-build.sourceforge.net/META-spec-v1.4.html
@@ -27,5 +27,5 @@
   bugtracker: https://github.com/toddr/Sys-Mmap/issues
   license: http://dev.perl.org/licenses/
   repository: http://github.com/toddr/Sys-Mmap/tree/master
-version: '0.20'
-x_serialization_backend: 'CPAN::Meta::YAML version 0.018'
+version: '0.21'
+x_serialization_backend: 'CPAN::Meta::YAML version 0.020'
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Sys-Mmap-0.20/Mmap.pm new/Sys-Mmap-0.21/Mmap.pm
--- old/Sys-Mmap-0.20/Mmap.pm   2020-02-13 19:34:40.000000000 +0100
+++ new/Sys-Mmap-0.21/Mmap.pm   2026-03-22 22:33:35.000000000 +0100
@@ -72,7 +72,9 @@
 memory. This memory region is inherited by any C<fork()>ed children.
 C<VARIABLE> will now refer to the contents of that file.  Any change to
 C<VARIABLE> will make an identical change to the file.  If C<LENGTH> is zero
-and a file is specified, the current length of the file will be used.  If
+and a file is specified, the current length of the file will be used.  (Note:
+the tied interface does not support C<OFFSET>, so this always maps the full
+file.)  If
 C<LENGTH> is larger then the file, and C<OPTIONALFILENAME> is provided, the
 file is grown to that length before being mapped.  This is the preferred
 interface, as it requires much less caution in handling the variable.
@@ -92,7 +94,15 @@
 address space, starting at offset C<OFFSET> and makes C<VARIABLE> refer to that
 memory. The C<OFFSET> argument can be omitted in which case it defaults to
 zero. The C<LENGTH> argument can be zero in which case a stat is done on
-C<FILEHANDLE> and the size of the underlying file is used instead.
+C<FILEHANDLE> and the file size is used to infer the mapping length.  If
+C<OFFSET> is also specified, the inferred length is C<file_size - OFFSET>
+(i.e. the remainder of the file from C<OFFSET> onward).  An exception is
+thrown if C<OFFSET> is at or beyond the end of the file.
+
+B<Caveat>: the underlying C<mmap()> system call requires the offset to be a
+multiple of the system page size (typically 4096 bytes).  Sys::Mmap handles
+non-page-aligned offsets internally by adjusting the mapping, but very large
+non-aligned offsets may map slightly more memory than the requested region.
 
 The C<PROTECTION> argument should be some ORed combination of the constants
 C<PROT_READ>, C<PROT_WRITE> and C<PROT_EXEC>, or else C<PROT_NONE>. The
@@ -179,7 +189,7 @@
 use strict;
 use warnings;
 
-our $VERSION = '0.20';
+our $VERSION = '0.21';
 
 our $AUTOLOAD; # For sub AUTOLOAD
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Sys-Mmap-0.20/Mmap.xs new/Sys-Mmap-0.21/Mmap.xs
--- old/Sys-Mmap-0.20/Mmap.xs   2020-02-13 19:34:40.000000000 +0100
+++ new/Sys-Mmap-0.21/Mmap.xs   2026-03-22 22:24:59.000000000 +0100
@@ -152,6 +152,49 @@
 
 static size_t pagesize = 0;
 
+/* Magic structure to track mmap info for proper cleanup */
+typedef struct {
+    void  *base_addr;  /* actual address returned by mmap() */
+    size_t total_len;  /* actual length passed to mmap() (len + slop) */
+} mmap_info_t;
+
+#define MMAP_MAGIC_TYPE PERL_MAGIC_ext
+
+static int mmap_magic_free(pTHX_ SV *sv, MAGIC *mg) {
+    mmap_info_t *info = (mmap_info_t *) mg->mg_ptr;
+    if (info) {
+        if (info->base_addr) {
+            munmap((MMAP_RETTYPE) info->base_addr, info->total_len);
+            info->base_addr = NULL;
+        }
+        Safefree(info);
+        mg->mg_ptr = NULL;
+    }
+    return 0;
+}
+
+static MGVTBL mmap_magic_vtbl = {
+    0,                /* get */
+    0,                /* set */
+    0,                /* len */
+    0,                /* clear */
+    mmap_magic_free,  /* free */
+    0,                /* copy */
+    0,                /* dup */
+    0                 /* local */
+};
+
+/* Find our mmap magic on an SV, or NULL if not present */
+static MAGIC *find_mmap_magic(SV *sv) {
+    MAGIC *mg;
+    if (SvTYPE(sv) >= SVt_PVMG) {
+        for (mg = SvMAGIC(sv); mg; mg = mg->mg_moremagic) {
+            if (mg->mg_type == MMAP_MAGIC_TYPE && mg->mg_virtual == 
&mmap_magic_vtbl)
+                return mg;
+        }
+    }
+    return NULL;
+}
 
 #if _FILE_OFFSET_BITS > 32
 #define get_off(a) (atoll(a))
@@ -229,7 +272,10 @@
              if (fstat(fd, &st) == -1) {
                   croak("mmap: no len provided, fstat failed, unable to infer 
length");
               }
-             len = st.st_size;
+             if (off >= st.st_size) {
+                 croak("mmap: offset (%"IVdf") is at or beyond end of file 
(size %"IVdf")", (IV)off, (IV)st.st_size);
+             }
+             len = st.st_size - off;
          }
         }
 
@@ -257,8 +303,21 @@
         /* would sv_usepvn() be cleaner/better/different? would still try to 
realloc... */
        SvPVX(var) = (char *) addr + slop;
        SvCUR_set(var, len);
-       SvLEN_set(var, slop);
+       SvLEN_set(var, 0);   /* must be 0 so Perl won't Safefree() the mmap'd 
pointer */
        SvPOK_only(var);
+
+        /* Attach magic to handle munmap on cleanup */
+        {
+            mmap_info_t *info;
+            MAGIC *mg;
+            Newxz(info, 1, mmap_info_t);
+            info->base_addr = (void *) addr;
+            info->total_len = len + slop;
+            mg = sv_magicext(var, NULL, MMAP_MAGIC_TYPE, &mmap_magic_vtbl,
+                             (const char *) info, 0);
+            mg->mg_flags |= MGf_LOCAL;
+        }
+
         ST(0) = sv_2mortal(newSVnv((IV) addr));
 
 SV *
@@ -277,9 +336,28 @@
             return;
         }
 
-        if (munmap((MMAP_RETTYPE) SvPVX(var) - SvLEN(var), SvCUR(var) + 
SvLEN(var)) == -1) {
-            croak("munmap failed! errno %d %s\n", errno, strerror(errno));
-            return;
+        {
+            MAGIC *mg = find_mmap_magic(var);
+            if (mg) {
+                mmap_info_t *info = (mmap_info_t *) mg->mg_ptr;
+                if (munmap((MMAP_RETTYPE) info->base_addr, info->total_len) == 
-1) {
+                    croak("munmap failed! errno %d %s\n", errno, 
strerror(errno));
+                    return;
+                }
+                info->base_addr = NULL;  /* prevent double munmap in magic 
free */
+            } else {
+                /* fallback for hardwire'd or legacy variables without magic */
+                /* SvLEN > 0 means this is a regular Perl string, not mmap'd */
+                if (SvLEN(var) != 0) {
+                    errno = EINVAL;
+                    croak("munmap failed! errno %d %s\n", errno, 
strerror(errno));
+                    return;
+                }
+                if (munmap((MMAP_RETTYPE) SvPVX(var), SvCUR(var)) == -1) {
+                    croak("munmap failed! errno %d %s\n", errno, 
strerror(errno));
+                    return;
+                }
+            }
         }
         SvREADONLY_off(var);
         SvPVX(var) = 0;
@@ -289,14 +367,37 @@
         ST(0) = &PL_sv_yes;
 
 void
-DESTROY(var) 
+DESTROY(var)
     SV *     var
     PROTOTYPE: $
     CODE:
         /* XXX refrain from dumping core if this var wasnt previously mmap'd*/
-        if (munmap((MMAP_RETTYPE) SvPVX(var), SvCUR(var)) == -1) {
-            croak("munmap failed! errno %d %s\n", errno, strerror(errno));
-            return;
+
+        /* For tied objects: DESTROY receives the blessed reference 
(\$mmap_sv),
+         * not the mmap'd SV itself.  Dereference to reach the actual mapping. 
*/
+        if (SvROK(var))
+            var = SvRV(var);
+
+        {
+            MAGIC *mg = find_mmap_magic(var);
+            if (mg) {
+                mmap_info_t *info = (mmap_info_t *) mg->mg_ptr;
+                if (info->base_addr) {
+                    if (munmap((MMAP_RETTYPE) info->base_addr, 
info->total_len) == -1) {
+                        croak("munmap failed! errno %d %s\n", errno, 
strerror(errno));
+                        return;
+                    }
+                    info->base_addr = NULL;
+                }
+            } else {
+                /* SvLEN > 0 means this is a regular Perl string, not mmap'd */
+                if (SvLEN(var) != 0)
+                    return;
+                if (munmap((MMAP_RETTYPE) SvPVX(var), SvCUR(var)) == -1) {
+                    croak("munmap failed! errno %d %s\n", errno, 
strerror(errno));
+                    return;
+                }
+            }
         }
         SvREADONLY_off(var);
         SvPVX(var) = 0;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Sys-Mmap-0.20/t/comprehensive.t 
new/Sys-Mmap-0.21/t/comprehensive.t
--- old/Sys-Mmap-0.20/t/comprehensive.t 1970-01-01 01:00:00.000000000 +0100
+++ new/Sys-Mmap-0.21/t/comprehensive.t 2026-03-22 22:24:59.000000000 +0100
@@ -0,0 +1,220 @@
+#! perl
+
+use strict;
+use warnings;
+
+use Test::More 'no_plan';
+use Sys::Mmap;
+use Fcntl qw(O_WRONLY O_CREAT O_TRUNC O_RDONLY O_RDWR);
+
+my $temp_file = "comprehensive.tmp";
+my $file_size = 8192;
+
+# Create a test file with known content
+sub create_test_file {
+    my ($size, $pattern) = @_;
+    $pattern = "ABCD1234" unless defined $pattern;
+    sysopen(my $fh, $temp_file, O_WRONLY|O_CREAT|O_TRUNC) or die "$temp_file: 
$!\n";
+    my $content = ($pattern x int($size / length($pattern) + 1));
+    $content = substr($content, 0, $size);
+    print $fh $content;
+    close $fh;
+    return $content;
+}
+
+# ---- Tied interface tests (new / TIESCALAR) ----
+
+{
+    my $content = create_test_file(4096);
+
+    # Collect any warnings during tied cleanup to verify no munmap failures
+    my @warnings;
+    local $SIG{__WARN__} = sub { push @warnings, $_[0] };
+
+    {
+        my $var;
+        my $obj = Sys::Mmap->new($var, 4096, $temp_file);
+        ok(defined $obj, "tied file: new() returns a defined object");
+        ok(tied($var), "tied file: variable is tied after new()");
+        is(length($var), 4096, "tied file: tied variable has correct length");
+        is($var, $content, "tied file: tied variable has correct content");
+
+        # Test STORE: writing through tied interface
+        my $new_data = "HELLO";
+        $var = $new_data;
+        is(substr($var, 0, length($new_data)), $new_data, "tied file: STORE 
writes data at beginning");
+        # Rest of mapping should be unchanged
+        is(substr($var, length($new_data), 4), substr($content, 
length($new_data), 4), "tied file: STORE preserves rest of data");
+        # Let $var and $obj go out of scope together
+    }
+    pass("tied file: variable cleaned up without crash");
+
+    # The DESTROY fix should prevent munmap failures on the blessed reference
+    my @munmap_warns = grep { /munmap failed/ } @warnings;
+    is(scalar @munmap_warns, 0, "tied file: no munmap failures during DESTROY 
cleanup");
+}
+
+{
+    my @warnings;
+    local $SIG{__WARN__} = sub { push @warnings, $_[0] };
+
+    {
+        my $var;
+        my $obj = Sys::Mmap->new($var, 4096);
+        ok(defined $obj, "tied anon: new() with anonymous memory returns 
defined object");
+        ok(tied($var), "tied anon: variable is tied for anonymous memory");
+        is(length($var), 4096, "tied anon: anonymous tied variable has correct 
length");
+
+        $var = "test data";
+        is(substr($var, 0, 9), "test data", "tied anon: STORE works on 
anonymous memory");
+    }
+    pass("tied anon: anonymous memory cleaned up without crash");
+
+    my @munmap_warns = grep { /munmap failed/ } @warnings;
+    is(scalar @munmap_warns, 0, "tied anon: no munmap failures during DESTROY 
cleanup");
+}
+
+{
+    my @warnings;
+    local $SIG{__WARN__} = sub { push @warnings, $_[0] };
+
+    # Create a tiny file
+    create_test_file(100);
+    is(-s $temp_file, 100, "tied grow: initial file is 100 bytes");
+
+    {
+        my $var;
+        Sys::Mmap->new($var, 4096, $temp_file);
+        ok(tied($var), "tied grow: tied to grown file");
+        is(length($var), 4096, "tied grow: tied variable reflects grown size");
+    }
+
+    # File should have been grown to 4096
+    ok(-s $temp_file >= 4096, "tied grow: file was grown to requested length");
+
+    my @munmap_warns = grep { /munmap failed/ } @warnings;
+    is(scalar @munmap_warns, 0, "tied grow: no munmap failures during DESTROY 
cleanup");
+}
+
+# ---- MAP_ANON tests ----
+
+{
+    my $data;
+    my $addr = mmap($data, 4096, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_ANON, 
*STDOUT);
+    ok(defined $addr, "MAP_ANON: mmap succeeds");
+    is(length($data), 4096, "MAP_ANON: mapping has correct length");
+
+    # Anonymous memory should be zero-filled
+    is($data, "\0" x 4096, "MAP_ANON: memory is zero-filled");
+
+    # Write and read back
+    substr($data, 0, 5) = "Hello";
+    is(substr($data, 0, 5), "Hello", "MAP_ANON: can write to region");
+
+    munmap($data);
+}
+
+{
+    my $data;
+    eval { mmap($data, 0, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_ANON, *STDOUT) 
};
+    like($@, qr/MAP_ANON.*no length/i, "MAP_ANON: len=0 croaks");
+}
+
+# ---- len=0 with offset: inferred length should be file_size - offset ----
+
+{
+    my $content = create_test_file(8192);
+
+    my $data;
+    sysopen(my $fh, $temp_file, O_RDONLY) or die "$temp_file: $!\n";
+    mmap($data, 0, PROT_READ, MAP_SHARED, $fh);
+    close $fh;
+
+    is(length($data), 8192, "len=0: infers full file size");
+    is($data, $content, "len=0: maps entire file content");
+    munmap($data);
+}
+
+{
+    my $content = create_test_file(8192);
+    my $offset = 4096;
+
+    my $data;
+    sysopen(my $fh, $temp_file, O_RDONLY) or die "$temp_file: $!\n";
+    mmap($data, 0, PROT_READ, MAP_SHARED, $fh, $offset);
+    close $fh;
+
+    is(length($data), 8192 - $offset, "len=0 with offset: infers file_size - 
offset");
+    is($data, substr($content, $offset), "len=0 with offset: content matches 
file from offset");
+    munmap($data);
+}
+
+{
+    my $content = create_test_file(8192);
+    my $offset = 256;  # likely not page-aligned
+
+    my $data;
+    sysopen(my $fh, $temp_file, O_RDONLY) or die "$temp_file: $!\n";
+    mmap($data, 0, PROT_READ, MAP_SHARED, $fh, $offset);
+    close $fh;
+
+    is(length($data), 8192 - $offset, "len=0 with non-aligned offset: infers 
correct remaining size");
+    is($data, substr($content, $offset), "len=0 with non-aligned offset: 
content matches");
+    munmap($data);
+}
+
+{
+    create_test_file(4096);
+
+    my $data;
+    sysopen(my $fh, $temp_file, O_RDONLY) or die "$temp_file: $!\n";
+    eval { mmap($data, 0, PROT_READ, MAP_SHARED, $fh, 4096) };
+    close $fh;
+    like($@, qr/offset.*beyond end of file/i, "len=0: offset at EOF croaks");
+}
+
+{
+    create_test_file(4096);
+
+    my $data;
+    sysopen(my $fh, $temp_file, O_RDONLY) or die "$temp_file: $!\n";
+    eval { mmap($data, 0, PROT_READ, MAP_SHARED, $fh, 8192) };
+    close $fh;
+    like($@, qr/offset.*beyond end of file/i, "len=0: offset beyond EOF 
croaks");
+}
+
+# ---- Explicit offset with explicit length ----
+
+{
+    my $content = create_test_file(8192);
+    my $offset = 4096;
+    my $len = 1024;
+
+    my $data;
+    sysopen(my $fh, $temp_file, O_RDONLY) or die "$temp_file: $!\n";
+    mmap($data, $len, PROT_READ, MAP_SHARED, $fh, $offset);
+    close $fh;
+
+    is(length($data), $len, "explicit offset+length: correct length");
+    is($data, substr($content, $offset, $len), "explicit offset+length: 
correct content");
+    munmap($data);
+}
+
+# ---- DESTROY cleanup (implicit munmap via scope exit) ----
+
+{
+    my $content = create_test_file(8192);
+
+    {
+        my $data;
+        sysopen(my $fh, $temp_file, O_RDONLY) or die "$temp_file: $!\n";
+        mmap($data, 0, PROT_READ, MAP_SHARED, $fh);
+        close $fh;
+        is(length($data), 8192, "DESTROY: mmap succeeded before scope exit");
+        # $data goes out of scope - DESTROY called implicitly
+    }
+    pass("DESTROY: survived without explicit munmap");
+}
+
+# Cleanup
+unlink($temp_file);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Sys-Mmap-0.20/t/offset.t new/Sys-Mmap-0.21/t/offset.t
--- old/Sys-Mmap-0.20/t/offset.t        1970-01-01 01:00:00.000000000 +0100
+++ new/Sys-Mmap-0.21/t/offset.t        2026-03-22 22:24:59.000000000 +0100
@@ -0,0 +1,44 @@
+#! perl
+
+use strict;
+use warnings;
+
+use Test::More tests => 4;
+
+use Sys::Mmap;
+use Fcntl qw(O_WRONLY O_CREAT O_TRUNC O_RDONLY);
+
+my $temp_file = "offset.tmp";
+my $file_size = 8192;
+
+# Create a file large enough to map with an offset
+sysopen(FOO, $temp_file, O_WRONLY|O_CREAT|O_TRUNC) or die "$temp_file: $!\n";
+print FOO "A" x $file_size;
+close FOO;
+
+# Test 1: mmap with non-zero offset and explicit munmap
+{
+    my $data;
+    sysopen(FOO, $temp_file, O_RDONLY) or die "$temp_file: $!\n";
+    mmap($data, 256, PROT_READ, MAP_SHARED, FOO, 256);
+    close FOO;
+    is(length($data), 256, "mmap with offset returns correct length");
+    is($data, "A" x 256, "mmap with offset returns correct data");
+    munmap($data);
+}
+
+# Test 2: mmap with non-zero offset, DESTROY cleanup (no explicit munmap)
+# This is the crash from GitHub issue #1 - segfault on cleanup when offset != 0
+{
+    my $data;
+    sysopen(FOO, $temp_file, O_RDONLY) or die "$temp_file: $!\n";
+    mmap($data, 256, PROT_READ, MAP_SHARED, FOO, 256);
+    close FOO;
+    is(length($data), 256, "mmap with offset (DESTROY path) returns correct 
length");
+    # $data goes out of scope here - DESTROY is called instead of explicit 
munmap
+    # Before the fix, this would segfault
+}
+
+pass("Survived DESTROY with non-zero offset (no segfault)");
+
+unlink($temp_file);

++++++ _scmsync.obsinfo ++++++
mtime: 1780844503
commit: 63b93509eec2f5031a2f343c3857d543e5287c2f85eb876636563b7f9cfa91a2
url: https://src.opensuse.org/perl/perl-Sys-Mmap
revision: 63b93509eec2f5031a2f343c3857d543e5287c2f85eb876636563b7f9cfa91a2
projectscmsync: https://src.opensuse.org/perl/_ObsPrj

++++++ build.specials.obscpio ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/.gitignore new/.gitignore
--- old/.gitignore      1970-01-01 01:00:00.000000000 +0100
+++ new/.gitignore      2026-06-07 17:01:43.000000000 +0200
@@ -0,0 +1 @@
+.osc

++++++ cpanspec.yml ++++++
--- /var/tmp/diff_new_pack.Uue1dT/_old  2026-06-09 14:28:44.361505157 +0200
+++ /var/tmp/diff_new_pack.Uue1dT/_new  2026-06-09 14:28:44.369505488 +0200
@@ -1,5 +1,5 @@
 ---
-#description_paragraphs: 3
+description_paragraphs: 3
 #description: |-
 #  override description from CPAN
 #summary: override summary from CPAN

Reply via email to