Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package ocaml for openSUSE:Factory checked 
in at 2026-11-01 22:21:16
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/ocaml (Old)
 and      /work/SRC/openSUSE:Factory/.ocaml.new.1255 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "ocaml"

Sun Nov  1 22:21:16 2026 rev:98 rq:1393968 version:5.5.2

Changes:
--------
--- /work/SRC/openSUSE:Factory/ocaml/ocaml.changes      2026-09-28 
10:37:23.243172534 +0200
+++ /work/SRC/openSUSE:Factory/.ocaml.new.1255/ocaml.changes    2026-11-01 
22:21:24.637005957 +0100
@@ -1,0 +2,6 @@
+Fri Oct 23 23:23:23 UTC 2026 - [email protected]
+
+- update to version 5.5.2
+  See included Changes for benefits and breaking changes
+
+-------------------------------------------------------------------

Old:
----
  ocaml-5.5.1.tar.xz

New:
----
  ocaml-5.5.2.tar.xz

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

Other differences:
------------------
++++++ ocaml.spec ++++++
--- /var/tmp/diff_new_pack.nCilQ3/_old  2026-11-01 22:21:25.910058644 +0100
+++ /var/tmp/diff_new_pack.nCilQ3/_new  2026-11-01 22:21:25.912058727 +0100
@@ -45,7 +45,7 @@
 %bcond_without suse_ocaml_use_rpm_license_macro
 
 Name:           ocaml
-Version:        5.5.1
+Version:        5.5.2
 Release:        0
 Summary:        OCaml Compiler and Programming Environment
 %if %{with suse_ocaml_use_rpm_license_macro}

++++++ _service ++++++
--- /var/tmp/diff_new_pack.nCilQ3/_old  2026-11-01 22:21:25.949060258 +0100
+++ /var/tmp/diff_new_pack.nCilQ3/_new  2026-11-01 22:21:25.953060423 +0100
@@ -166,7 +166,7 @@
     <param name="exclude">utils/HACKING.adoc</param>
     <param name="exclude">utils/dune</param>
     <param name="filename">ocaml</param>
-    <param name="revision">46e1c324fb9e9f21f52c9cc3399020f7ef8b9b91</param>
+    <param name="revision">c7b6787eb4c2b4a89e2c190e7ffdfa25082d1a6d</param>
     <param name="scm">git</param>
     <param name="submodules">disable</param>
     <param name="url">https://github.com/ocaml/ocaml.git</param>

++++++ ocaml-5.5.1.tar.xz -> ocaml-5.5.2.tar.xz ++++++
++++ 2026 lines of diff (skipped)
++++    retrying with extended exclude list
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude 
config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 
--exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh 
old/ocaml-5.5.1/Changes new/ocaml-5.5.2/Changes
--- old/ocaml-5.5.1/Changes     2026-09-04 13:16:34.000000000 +0200
+++ new/ocaml-5.5.2/Changes     2026-10-23 13:52:23.000000000 +0200
@@ -1,3 +1,48 @@
+OCaml 5.5.2
+-----------
+
+### Bug fixes:
+
+- #15045: Atomic loads whose results are unused should not be removed
+  during dead-code elimination.
+  (Xavier Clerc, review by Steven Dolan and KC Sivaramakrishnan)
+
+- #15067, #15071: Fix detection of functions available in the future on macOS.
+  (Antonin Décimo, review by Nicolás Ojeda Bär and Damien Doligez)
+
+- #15112, OSEC-2026-22: `Unix.map_file`: protect against overflow
+  when computing the data size.
+  (Xavier Leroy and Nicolás Ojeda Bär, review by Nicolás Ojeda Bär
+  and Edwin Török)
+
+- #15113, OSEC-2026-21: `Str.string_partial_match`: make sure captured groups
+  are valid.
+  (Xavier Leroy, review by Nicolás Ojeda Bär and Edwin Török)
+
+- #15115, OSEC-2026-23: Fix multiple issues in demarshaling
+  (`Marshal.from_{channel,string,bytes}`)
+  (Xavier Leroy, review by Nicolás Ojeda Bär)
+
+- #15133, OSEC 2026-24: Multiple issues in command quoting on Windows
+  (Xavier Leroy and Nicolás Ojeda Bär, review by Nicolás Ojeda Bär)
+
+- #15119, OSEC-2026-25: Harden decoding of runtime events messages from
+  ring buffers.
+  (Sadiq Jaffer, report by Hannes Mehnert, review by Olivier Nicole and
+  Edwin Török)
+
+- #15177, OSEC-2026-26: Maintain custom events cache integrity.
+  (Sadiq Jaffer, report by Hannes Mehnert, review by Edwin Török)
+
+- #15043, #15076: runtime events library, fix an infinite loop when a user
+  event is larger than half the ring buffer.
+  (Tim McGilchrist, review by Sadiq Jaffer)
+
+- #15185, #15187: fix a pattern-matching miscompilation on certain
+  combinations of immediate ranges and redundant patterns
+  (Gabriel Scherer, report by Alperer Keleş,
+   review by Vincent Laviron and Florian Angeletti)
+
 OCaml 5.5.1 (4 September 2026)
 ------------------------------
 
@@ -61,8 +106,8 @@
   artefacts) as well as the debug info packed into str.a and unix.a.
   (Bernhard M. Wiedemann, review by David Allsopp and Stefan Muenzel)
 
-- #15019: `Marshal.from_{string,bytes}`: guard against overflow in
-  the computation of the total data length.
+- #15019, #15030, OSEC-2026-18: `Marshal.from_{string,bytes}`: guard against
+  overflow in the computation of the total data length.
   (Xavier Leroy, report by Akshay Singh, review by Nicolás Ojeda Bär
   and Antonin Décimo)
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude 
config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 
--exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh 
old/ocaml-5.5.1/VERSION new/ocaml-5.5.2/VERSION
--- old/ocaml-5.5.1/VERSION     2026-09-04 13:16:34.000000000 +0200
+++ new/ocaml-5.5.2/VERSION     2026-10-23 13:52:23.000000000 +0200
@@ -1,4 +1,4 @@
-5.5.1
+5.5.2
 
 # Starting with OCaml 4.14, although the version string that appears above is
 # still correct and this file can thus still be used to figure it out,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude 
config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 
--exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh 
old/ocaml-5.5.1/asmcomp/mach.ml new/ocaml-5.5.2/asmcomp/mach.ml
--- old/ocaml-5.5.1/asmcomp/mach.ml     2026-09-04 13:16:34.000000000 +0200
+++ new/ocaml-5.5.2/asmcomp/mach.ml     2026-10-23 13:52:23.000000000 +0200
@@ -155,7 +155,8 @@
   | Icall_ind | Icall_imm _ | Itailcall_ind | Itailcall_imm _
   | Iextcall _ | Istackoffset _ | Istore _ | Ialloc _ | Ipoll _
   | Idls_get
-  | Iintop(Icheckbound) | Iintop_imm(Icheckbound, _) | Iopaque -> false
+  | Iintop(Icheckbound) | Iintop_imm(Icheckbound, _) | Iopaque
+  | Iload { is_atomic = true; _ } -> false
   | Ispecific sop -> Arch.operation_is_pure sop
   | _ -> true
 
Binary files old/ocaml-5.5.1/boot/ocamlc and new/ocaml-5.5.2/boot/ocamlc differ
Binary files old/ocaml-5.5.1/boot/ocamllex and new/ocaml-5.5.2/boot/ocamllex 
differ
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude 
config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 
--exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh 
old/ocaml-5.5.1/build-aux/ocaml_version.m4 
new/ocaml-5.5.2/build-aux/ocaml_version.m4
--- old/ocaml-5.5.1/build-aux/ocaml_version.m4  2026-09-04 13:16:34.000000000 
+0200
+++ new/ocaml-5.5.2/build-aux/ocaml_version.m4  2026-10-23 13:52:23.000000000 
+0200
@@ -35,7 +35,7 @@
 m4_define([OCAML__VERSION_MAJOR], [5])
 m4_define([OCAML__VERSION_MINOR], [5])
 m4_define([OCAML__RELEASE_NUMBER], [21])
-m4_define([OCAML__VERSION_PATCHLEVEL], [1])
+m4_define([OCAML__VERSION_PATCHLEVEL], [2])
 
 # Note that the OCAML__VERSION_EXTRA string defined below is always empty
 # for officially-released versions of OCaml.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude 
config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 
--exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh 
old/ocaml-5.5.1/configure.ac new/ocaml-5.5.2/configure.ac
--- old/ocaml-5.5.1/configure.ac        2026-09-04 13:16:34.000000000 +0200
+++ new/ocaml-5.5.2/configure.ac        2026-10-23 13:52:23.000000000 +0200
@@ -1151,6 +1151,12 @@
     internal_cflags="$cc_warnings"],
   [common_cflags="-O"])
 
+AS_CASE([$target],
+  [*-apple-darwin*],
+    [AX_CHECK_COMPILE_FLAG([-Werror=unguarded-availability-new],
+      [common_cflags="-Werror=unguarded-availability-new $common_cflags"], [],
+      [$warn_error_flag])])
+
 # Enable SSE2 on x86 mingw to avoid using 80-bit registers.
 # Enable 64-bit time_t in time.h
 AS_CASE([$target],
@@ -2551,11 +2557,17 @@
 
 ## dup3
 
-AC_CHECK_FUNC([dup3], [AC_DEFINE([HAS_DUP3], [1])])
+OCAML_CHECK_DECL_MACOS([dup3],
+  [AC_CHECK_FUNC([dup3], [AC_DEFINE([HAS_DUP3], [1])])], [],
+  [#define _GNU_SOURCE
+  AC_INCLUDES_DEFAULT])
 
 ## pipe2
 
-AC_CHECK_FUNC([pipe2], [AC_DEFINE([HAS_PIPE2], [1])])
+OCAML_CHECK_DECL_MACOS([pipe2],
+  [AC_CHECK_FUNC([pipe2], [AC_DEFINE([HAS_PIPE2], [1])])], [],
+  [#define _GNU_SOURCE
+  AC_INCLUDES_DEFAULT])
 
 ## accept4
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude 
config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 
--exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh 
old/ocaml-5.5.1/lambda/matching.ml new/ocaml-5.5.2/lambda/matching.ml
--- old/ocaml-5.5.1/lambda/matching.ml  2026-09-04 13:16:34.000000000 +0200
+++ new/ocaml-5.5.2/lambda/matching.ml  2026-10-23 13:52:23.000000000 +0200
@@ -2795,6 +2795,23 @@
   | [] -> (low, high)
   | (x, _) :: _ -> (x, last high l)
 
+(** [as_interval_canfail fail ~low ~high] takes a sorted list of
+    (integer key, action) pairs, for example
+      0 -> act0
+      1 -> act1
+      2 -> act1
+      4 -> act1
+      5 -> act1
+   and returns a sorted list of contiguous intervals partitioning
+   [low; high], for example
+     [low; -1] -> fail
+     [0] -> act0
+     [1; 2] -> act1
+     [3] -> fail
+     [4; 5] -> act1
+     [6; high] -> fail
+   with missing keys mapped to the [fail] action.
+*)
 let as_interval_canfail fail ~low ~high l =
   let store = StoreExp.mk_store () in
   let do_store _tag act =
@@ -2804,7 +2821,22 @@
     *)
     i
   in
-  let rec nofail_rec cur_low cur_high cur_act = function
+  (* cover [low; high] with the provided mapping *)
+  let rec init_rec = function
+    | [] -> [ (low, high, 0) ]
+    | (i, act_i) :: rem ->
+        let index = do_store "INIT" act_i in
+        if index = 0 then
+          fail_rec low rem
+        else if low < i then
+          (low, i - 1, 0) :: nofail_rec i i index rem
+        else
+          nofail_rec i i index rem
+
+  (* cover [cur_low; high] with the provided mapping, assuming that:
+     - the keys are all within [cur_low; high]
+     - [cur_low; cur_high] goes to [cur_act] *)
+  and nofail_rec cur_low cur_high cur_act = function
     | [] ->
         if cur_high = high then
           [ (cur_low, cur_high, cur_act) ]
@@ -2816,42 +2848,49 @@
           if act_index = cur_act then
             nofail_rec cur_low i cur_act rem
           else if act_index = 0 then
-            (cur_low, i - 1, cur_act) :: fail_rec i i rem
+            (cur_low, i - 1, cur_act) :: fail_rec i rem
           else
             (cur_low, i - 1, cur_act) :: nofail_rec i i act_index rem
         else if act_index = 0 then
           (cur_low, cur_high, cur_act)
-          :: fail_rec (cur_high + 1) (cur_high + 1) all
+          :: fail_rec (cur_high + 1) all
         else
           (cur_low, cur_high, cur_act)
           :: (cur_high + 1, i - 1, 0)
           :: nofail_rec i i act_index rem
-  and fail_rec cur_low cur_high = function
-    | [] -> [ (cur_low, cur_high, 0) ]
+
+  (* cover [cur_low; high] with the provided mapping, assuming that:
+     - the keys are all within [cur_low; high]
+     - [cur_low] goes to [fail] *)
+  and fail_rec cur_low = function
+    | [] -> [ (cur_low, high, 0) ]
     | (i, act_i) :: rem ->
         let index = do_store "YES" act_i in
         if index = 0 then
-          fail_rec cur_low i rem
+          fail_rec cur_low rem
         else
           (cur_low, i - 1, 0) :: nofail_rec i i index rem
   in
-  let init_rec = function
-    | [] -> [ (low, high, 0) ]
-    | (i, act_i) :: rem ->
-        let index = do_store "INIT" act_i in
-        if index = 0 then
-          fail_rec low i rem
-        else if low < i then
-          (low, i - 1, 0) :: nofail_rec i i index rem
-        else
-          nofail_rec i i index rem
-  in
-  assert (do_store "FAIL" fail = 0);
-
-  (* fail has action index 0 *)
+  let fail_index = do_store "FAIL" fail in
+  assert (fail_index = 0);
   let r = init_rec l in
   (Array.of_list r, store)
 
+(** [as_interval_nofail] takes a sorted list of
+    (integer key, action) pairs, for example:
+     -1 -> act0
+     1 -> act0
+     2 -> act1
+     4 -> act1
+     5 -> act1
+   and returns a sorted list of contiguous intervals, for example
+     [-1; 1] -> act0
+     [2] -> act1
+     [3] -> act0
+     [4; 5] -> act1
+   with the first action (here [act0]) used for missing keys in the
+   convex hull of the input keys.
+*)
 let as_interval_nofail l =
   let store = StoreExp.mk_store () in
   let rec some_hole = function
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude 
config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 
--exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh 
old/ocaml-5.5.1/ocaml-variants.opam new/ocaml-5.5.2/ocaml-variants.opam
--- old/ocaml-5.5.1/ocaml-variants.opam 2026-09-04 13:16:34.000000000 +0200
+++ new/ocaml-5.5.2/ocaml-variants.opam 2026-10-23 13:52:23.000000000 +0200
@@ -1,7 +1,7 @@
 opam-version: "2.0"
-version: "5.5.1"
+version: "5.5.2+trunk"
 license: "LGPL-2.1-or-later WITH OCaml-LGPL-linking-exception"
-synopsis: "Official release of OCaml 5.5.1"
+synopsis: "Official OCaml 5.5.2 release"
 maintainer: "[email protected]"
 authors: [
   "Xavier Leroy"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude 
config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 
--exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh 
old/ocaml-5.5.1/otherlibs/runtime_events/runtime_events_consumer.c 
new/ocaml-5.5.2/otherlibs/runtime_events/runtime_events_consumer.c
--- old/ocaml-5.5.1/otherlibs/runtime_events/runtime_events_consumer.c  
2026-09-04 13:16:34.000000000 +0200
+++ new/ocaml-5.5.2/otherlibs/runtime_events/runtime_events_consumer.c  
2026-10-23 13:52:23.000000000 +0200
@@ -534,9 +534,15 @@
         continue;
       }
 
+      /* Every message carries a header and a timestamp, except runtime
+         padding (EV_INTERNAL) which is header only. EV_INTERNAL and
+         EV_USER_MSG_TYPE_UNIT share the same type value, so we need to
+         make sure it's EV_INTERNAL and a runtime (rather than user)
+         message. */
       if (!msg_length
           || (msg_length < 2
-              && RUNTIME_EVENTS_ITEM_TYPE(header) != EV_INTERNAL)) {
+              && !(RUNTIME_EVENTS_ITEM_IS_RUNTIME(header)
+                   && RUNTIME_EVENTS_ITEM_TYPE(header) == EV_INTERNAL))) {
         atomic_store(&cursor->cursor_in_poll, 0);
         return E_CORRUPT_STREAM;
       }
@@ -577,7 +583,8 @@
           break;
         case EV_ALLOC:
           if (cursor->alloc) {
-            if (msg_length < 3) {
+            /* the alloc callback reads every bucket */
+            if (msg_length < 2 + RUNTIME_EVENTS_NUM_ALLOC_BUCKETS) {
               atomic_store(&cursor->cursor_in_poll, 0);
               return E_CORRUPT_STREAM;
             }
@@ -660,7 +667,11 @@
             break;
           default: // custom
             if (cursor->user_custom) {
-              /* msg_length could be genuinely 2 here */
+              /* we have to have a message length of at least 3 */
+              if (msg_length < 3) {
+                atomic_store(&cursor->cursor_in_poll, 0);
+                return E_CORRUPT_STREAM;
+              }
               if( !cursor->user_custom(domain_num, callback_data, buf[1],
                                       event_id, event_name,
                                       msg_length - 2, &buf[2]) ) {
@@ -717,6 +728,11 @@
   value* callbacks_val;
   value* exception;
   value* wrapper;
+  /* set by a callback that detects a malformed event, since callbacks can
+     only stop the read loop and cannot return E_CORRUPT_STREAM themselves.
+     The exception field in this struct is only for carrying exceptions
+     raised by callbacks we call. */
+  bool corrupt_stream;
 };
 
 static int ml_runtime_begin(int domain_id, void *callback_data,
@@ -950,12 +966,17 @@
   CAMLreturnT(int, 1);
 }
 
+/* Returns Val_none if the event is unknown and of type
+   EV_USER_ML_TYPE_CUSTOM (see caml_runtime_events_user_resolve), or if the
+   resolved event's type does not match event_type, in which case
+   *corrupt_stream is also set. */
 static value caml_runtime_events_user_resolve_cached(
   value wrapper_root, uintnat event_id, char* event_name,
-  ev_user_ml_type event_type)
+  ev_user_ml_type event_type, bool* corrupt_stream)
 {
   CAMLparam1(wrapper_root);
-  CAMLlocal3(event, cache_resized, cache);
+  CAMLlocal4(event, cache_resized, cache, resolved_type);
+  bool cache_hit = false;
 
   cache = Field(wrapper_root, 2);
 
@@ -977,15 +998,36 @@
 
   uintnat len = Wosize_val(cache);
 
-  if (event_id < len) {
-    if (Is_block(Field(cache, event_id))) {
-      // cache hit !
-      CAMLreturn (Field(cache, event_id));
+  if (event_id < len && Is_block(Field(cache, event_id))) {
+    // cache hit !
+    event = Field(cache, event_id);
+    cache_hit = true;
+  } else {
+    // we never encountered this ID
+    event = caml_runtime_events_user_resolve(event_name, event_type);
+  }
+
+  // The event is resolved by name, or by a previously cached ID, independently
+  // of the message type read from the ring, so a malformed stream can pair a
+  // message of one type with an event declared with another. In that case
+  // the stream is corrupt. see the comment in
+  // user_events_find_callback_list_for_event_type: the resolved type is a
+  // block iff it is a custom event.
+  if (Is_block(event)) {
+    resolved_type = Field(event, 2);
+    bool type_matches = event_type == EV_USER_ML_TYPE_CUSTOM
+                          ? Is_block(resolved_type)
+                          : resolved_type == Val_int(event_type);
+
+    if (!type_matches) {
+      *corrupt_stream = true;
+      CAMLreturn(Val_none);
     }
   }
 
-  // we never encountered this ID
-  event = caml_runtime_events_user_resolve(event_name, event_type);
+  if (cache_hit) {
+    CAMLreturn(event);
+  }
 
   if (event_id >= len) {
     // we grow the cache to fit the event
@@ -1028,7 +1070,13 @@
 
   event = caml_runtime_events_user_resolve_cached(wrapper_root, event_id,
                                                                 event_name,
-                                                         EV_USER_ML_TYPE_UNIT);
+                                                         EV_USER_ML_TYPE_UNIT,
+                                    &holder->corrupt_stream);
+
+  // Val_none is only returned for a corrupt stream here
+  if (event == Val_none) {
+    CAMLreturnT(int, 0);
+  }
 
   callback_list = user_events_find_callback_list_for_event_type(callbacks_root,
                                                                 event);
@@ -1066,7 +1114,13 @@
 
   event = caml_runtime_events_user_resolve_cached(wrapper_root, event_id,
                                                                 event_name,
-                                                          
EV_USER_ML_TYPE_SPAN);
+                                                          EV_USER_ML_TYPE_SPAN,
+                                    &holder->corrupt_stream);
+
+  // Val_none is only returned for a corrupt stream here
+  if (event == Val_none) {
+    CAMLreturnT(int, 0);
+  }
 
   callback_list = user_events_find_callback_list_for_event_type(callbacks_root,
                                                                 event);
@@ -1103,7 +1157,13 @@
 
   event = caml_runtime_events_user_resolve_cached(wrapper_root, event_id,
                                                                   event_name,
-                                   EV_USER_ML_TYPE_INT);
+                                   EV_USER_ML_TYPE_INT,
+                                    &holder->corrupt_stream);
+
+  // Val_none is only returned for a corrupt stream here
+  if (event == Val_none) {
+    CAMLreturnT(int, 0);
+  }
 
   callback_list = user_events_find_callback_list_for_event_type(callbacks_root,
                                                                 event);
@@ -1142,13 +1202,15 @@
 
   event = caml_runtime_events_user_resolve_cached(wrapper_root, event_id,
                                                                 event_name,
-                                    EV_USER_ML_TYPE_CUSTOM);
+                                    EV_USER_ML_TYPE_CUSTOM,
+                                    &holder->corrupt_stream);
 
   // the function may return Val_none if the event is unknown
-  // (see caml_runtime_events_user_resolve)
+  // (see caml_runtime_events_user_resolve), in which case we skip it, or if
+  // the stream is corrupt, in which case we stop
   if (event == Val_none) {
     CAMLdrop;
-    return 1;
+    return !holder->corrupt_stream;
   }
 
   event_type = Field(event, 2);
@@ -1161,12 +1223,24 @@
     // deserialize the value and prepare the callback payload
 
     const char* data_str = (const char*) event_data;
+
+    // caml_runtime_events_read_poll has already checked this
+    CAMLassert(event_data_len >= 1);
+
     uintnat string_len = event_data_len * sizeof(uint64_t) - 1;
     // because the ring buffer is 64-bits aligned, the whole ocaml value is
     // transferred, including the padding bytes and the last byte containing
     // the number of padding bytes. This information is crucial to determine
     // the true size of the string.
-    uintnat caml_string_len = string_len - data_str[string_len];
+    uintnat caml_string_len =
+      string_len - (unsigned char)data_str[string_len];
+
+    // if the string length is over the max msg length, the stream is
+    // corrupt.
+    if (caml_string_len > RUNTIME_EVENTS_MAX_MSG_LENGTH) {
+      holder->corrupt_stream = 1;
+      CAMLreturnT(int, 0);
+    }
 
     record = Field(event_type, 0);
     deserializer = Field(record, 1);
@@ -1299,7 +1373,7 @@
   runtime_events_error res;
 
   struct callbacks_exception_holder holder = {
-    &callbacks_val, &exception, &wrapper };
+    &callbacks_val, &exception, &wrapper, 0 };
   exception = Val_unit;
 
   if (cursor == NULL) {
@@ -1318,6 +1392,11 @@
     caml_raise(exception);
   }
 
+  /* Check if a callback early exited because of a malformed event */
+  if (holder.corrupt_stream) {
+    res = E_CORRUPT_STREAM;
+  }
+
   if (res != E_SUCCESS) {
     switch (res) {
     case E_CURSOR_POLL_BUSY:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude 
config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 
--exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh 
old/ocaml-5.5.1/otherlibs/str/strstubs.c 
new/ocaml-5.5.2/otherlibs/str/strstubs.c
--- old/ocaml-5.5.1/otherlibs/str/strstubs.c    2026-09-04 13:16:34.000000000 
+0200
+++ new/ocaml-5.5.2/otherlibs/str/strstubs.c    2026-10-23 13:52:23.000000000 
+0200
@@ -134,7 +134,8 @@
   res = caml_alloc(n * 2, 0);
   for (int i = 0; i < n; i++) {
     group = &(groups[i]);
-    if (group->start == NULL || group->end == NULL) {
+    if (group->start == NULL || group->end == NULL
+        || group->start > group->end) {
       Field(res, i * 2) = Val_int(-1);
       Field(res, i * 2 + 1) = Val_int(-1);
     } else {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude 
config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 
--exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh 
old/ocaml-5.5.1/otherlibs/unix/mmap_unix.c 
new/ocaml-5.5.2/otherlibs/unix/mmap_unix.c
--- old/ocaml-5.5.1/otherlibs/unix/mmap_unix.c  2026-09-04 13:16:34.000000000 
+0200
+++ new/ocaml-5.5.2/otherlibs/unix/mmap_unix.c  2026-10-23 13:52:23.000000000 
+0200
@@ -130,7 +130,12 @@
      dimension if that dimension wasn't specified) */
   array_size = caml_ba_element_size[flags & CAML_BA_KIND_MASK];
   for (intnat i = 0; i < num_dims; i++)
-    if (dim[i] != -1) array_size *= dim[i];
+    if (dim[i] != -1) {
+      if (caml_umul_overflow(array_size, dim[i], &array_size)) {
+        caml_leave_blocking_section();
+        caml_failwith("Unix.map_file: array too big to fit in memory");
+      }
+    }
   /* Check if the major dimension is unknown */
   if (dim[major_dim] == -1) {
     /* Determine major dimension from file size */
@@ -138,17 +143,27 @@
       caml_leave_blocking_section();
       caml_failwith("Unix.map_file: file position exceeds file size");
     }
-    data_size = file_size - startpos;
-    dim[major_dim] = (uintnat) (data_size / array_size);
-    array_size = dim[major_dim] * array_size;
-    if (array_size != data_size) {
-      caml_leave_blocking_section();
-      caml_failwith("Unix.map_file: file size doesn't match array dimensions");
+    if (array_size == 0) {
+      dim[major_dim] = 0;
+    } else {
+      data_size = file_size - startpos;
+      dim[major_dim] = (uintnat) (data_size / array_size);
+      if (caml_umul_overflow(array_size, dim[major_dim], &array_size)
+          || array_size != data_size) {
+        caml_leave_blocking_section();
+        caml_failwith("Unix.map_file: file size doesn't match "
+                      "array dimensions");
+      }
     }
   } else {
     /* Check that file is large enough, and grow it otherwise */
-    if (file_size < startpos + array_size) {
-      if (caml_grow_file(fd, startpos + array_size) == -1) { /* PR#5543 */
+    file_offset min_file_size = startpos + array_size;
+    if (min_file_size < 0 || min_file_size < startpos) {
+      caml_leave_blocking_section();
+      caml_failwith("Unix.map_file: array too big to fit in the file");
+    }
+    if (file_size < min_file_size) {
+      if (caml_grow_file(fd, min_file_size) == -1) { /* PR#5543 */
         caml_leave_blocking_section();
         caml_uerror("map_file", Nothing);
       }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude 
config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 
--exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh 
old/ocaml-5.5.1/otherlibs/unix/unix.mli new/ocaml-5.5.2/otherlibs/unix/unix.mli
--- old/ocaml-5.5.1/otherlibs/unix/unix.mli     2026-09-04 13:16:34.000000000 
+0200
+++ new/ocaml-5.5.2/otherlibs/unix/unix.mli     2026-10-23 13:52:23.000000000 
+0200
@@ -896,7 +896,14 @@
     the redirection and causes the new process to have the same standard
     output as the current process.  The executable file [prog] is searched in
     the path.  The new process has the same environment as the current
-    process. *)
+    process.
+
+    @raise Failure on Windows if the program [prog] is a [.bat] or [.cmd]
+    script and either [prog] or [args] contain characters that cannot be
+    securely passed to a script, such as [" | & , ; < = > ^ % "].
+    If you really need to pass these characters to a script, consider
+    using {!Unix.system} instead.
+ *)
 
 val create_process_env :
   string -> string array -> string array -> file_descr ->
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude 
config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 
--exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh 
old/ocaml-5.5.1/otherlibs/unix/unixLabels.mli 
new/ocaml-5.5.2/otherlibs/unix/unixLabels.mli
--- old/ocaml-5.5.1/otherlibs/unix/unixLabels.mli       2026-09-04 
13:16:34.000000000 +0200
+++ new/ocaml-5.5.2/otherlibs/unix/unixLabels.mli       2026-10-23 
13:52:23.000000000 +0200
@@ -896,7 +896,14 @@
     the redirection and causes the new process to have the same standard
     output as the current process.  The executable file [prog] is searched in
     the path.  The new process has the same environment as the current
-    process. *)
+    process.
+
+    @raise Failure on Windows if the program [prog] is a [.bat] or [.cmd]
+    script and either [prog] or [args] contain characters that cannot be
+    securely passed to a script, such as [" | & , ; < = > ^ % "].
+    If you really need to pass these characters to a script, consider
+    using {!Unix.system} instead.
+ *)
 
 val create_process_env :
   prog:string -> args:string array -> env:string array -> stdin:file_descr ->
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude 
config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 
--exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh 
old/ocaml-5.5.1/otherlibs/unix/unix_unix.ml 
new/ocaml-5.5.2/otherlibs/unix/unix_unix.ml
--- old/ocaml-5.5.1/otherlibs/unix/unix_unix.ml 2026-09-04 13:16:34.000000000 
+0200
+++ new/ocaml-5.5.2/otherlibs/unix/unix_unix.ml 2026-10-23 13:52:23.000000000 
+0200
@@ -400,6 +400,7 @@
      = "caml_unix_map_file_bytecode" "caml_unix_map_file"
 
 let map_file fd ?(pos=0L) kind layout shared dims =
+  if pos < 0L then invalid_arg "Unix.map_file: negative position";
   map_internal fd kind layout shared dims pos
 
 (* File permissions and ownership *)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude 
config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 
--exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh 
old/ocaml-5.5.1/otherlibs/unix/unix_win32.ml 
new/ocaml-5.5.2/otherlibs/unix/unix_win32.ml
--- old/ocaml-5.5.1/otherlibs/unix/unix_win32.ml        2026-09-04 
13:16:34.000000000 +0200
+++ new/ocaml-5.5.2/otherlibs/unix/unix_win32.ml        2026-10-23 
13:52:23.000000000 +0200
@@ -436,6 +436,7 @@
      = "caml_unix_map_file_bytecode" "caml_unix_map_file"
 
 let map_file fd ?(pos=0L) kind layout shared dims =
+  if pos < 0L then invalid_arg "Unix.map_file: negative position";
   map_internal fd kind layout shared dims pos
 
 (* File permissions and ownership *)
@@ -995,8 +996,52 @@
     file_descr -> file_descr -> file_descr -> int
   = "caml_unix_create_process" "caml_unix_create_process_native"
 
-let make_cmdline args =
-  String.concat " " (List.map maybe_quote (Array.to_list args))
+(* Some arguments cannot be safely passed to .bat/.cmd scripts.
+   Those that can be safely passed use different quoting conventions
+   than those of [maybe_quote], which are for passing arguments to
+   .exe binaries. *)
+
+let check_safe_for_script s =
+  if String.exists
+      (function '\n' | '\r' | '"' | '%' | '&' | ','
+              | ';'  | '<'  | '=' | '>' | '^' | '|'
+                  -> true
+              | _ -> false)
+      s
+  then failwith ("Unix.create_process: unquotable argument to script: " ^ s)
+
+let double_quote s =
+  "\"" ^ s ^ "\""
+
+let maybe_quote_for_script s =
+  if s = "" || String.exists (function ' ' | '\t' -> true | _ -> false) s
+  then double_quote s
+  else s
+
+(* Windows ignores trailing spaces and dots in filenames.
+   This complicates the detection of the file extension. *)
+
+let filename_extension s =
+  let n = ref (String.length s) in
+  while !n > 0 && (s.[!n-1] = '.' || s.[!n-1] = ' ') do decr n done;
+  Filename.extension (String.sub s 0 !n)
+
+let make_cmdline prog args =
+  let ext = String.lowercase_ascii (filename_extension prog) in
+  if ext = ".bat" || ext = ".cmd" then begin
+    (* args.(0) is replaced by the script name. *)
+    (* Forward slashes in the script name can be confused for cmd.exe flags. *)
+    let arg0 = String.map (function '/' -> '\\' | c -> c) prog
+    and arg1n = match Array.to_list args with [] -> [] | _ :: t -> t in
+    check_safe_for_script arg0;
+    List.iter check_safe_for_script arg1n;
+    (* Always quote the script name to avoid possible mis-parsing of
+       "prog.bat arg1.bat" as a script called with zero arguments. *)
+    double_quote
+      (String.concat " "
+         (double_quote arg0 :: List.map maybe_quote_for_script arg1n))
+  end else
+    String.concat " " (List.map maybe_quote (Array.to_list args))
 
 let make_process_env env =
   Array.iter
@@ -1005,10 +1050,10 @@
   String.concat "\000" (Array.to_list env) ^ "\000"
 
 let create_process prog args fd1 fd2 fd3 =
-  create_process_stub prog (make_cmdline args) None fd1 fd2 fd3
+  create_process_stub prog (make_cmdline prog args) None fd1 fd2 fd3
 
 let create_process_env prog args env fd1 fd2 fd3 =
-  create_process_stub prog (make_cmdline args)
+  create_process_stub prog (make_cmdline prog args)
                       (Some(make_process_env env))
                       fd1 fd2 fd3
 
@@ -1105,13 +1150,13 @@
   (inchan, outchan, errchan)
 
 let open_process_args_in prog args =
-  open_process_cmdline_in prog (make_cmdline args)
+  open_process_cmdline_in prog (make_cmdline prog args)
 let open_process_args_out prog args =
-  open_process_cmdline_out prog (make_cmdline args)
+  open_process_cmdline_out prog (make_cmdline prog args)
 let open_process_args prog args =
-  open_process_cmdline prog (make_cmdline args)
+  open_process_cmdline prog (make_cmdline prog args)
 let open_process_args_full prog args =
-  open_process_cmdline_full prog (make_cmdline args)
+  open_process_cmdline_full prog (make_cmdline prog args)
 
 let open_process_shell fn cmd =
   let shell =
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude 
config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 
--exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh 
old/ocaml-5.5.1/runtime/intern.c new/ocaml-5.5.2/runtime/intern.c
--- old/ocaml-5.5.1/runtime/intern.c    2026-09-04 13:16:34.000000000 +0200
+++ new/ocaml-5.5.2/runtime/intern.c    2026-10-23 13:52:23.000000000 +0200
@@ -21,6 +21,7 @@
 
 #include <string.h>
 #include <stdio.h>
+#include <stdbool.h>
 #include "caml/alloc.h"
 #include "caml/callback.h"
 #include "caml/codefrag.h"
@@ -42,10 +43,12 @@
 struct intern_item {
   volatile value * dest;
   intnat arg;
-  enum {
+  enum intern_operation {
     OReadItems, /* read arg items and store them in dest[0], dest[1], ... */
+    OReadItemsOrCodePointers, /* likewise, but code pointers are allowed */
     OFreshOID,  /* generate a fresh OID and store it in *dest */
-    OShift      /* offset *dest by arg */
+    OShift,     /* offset *dest by arg */
+    OCheckClosure /* check that dest is a well-formed closure */
   } op;
 };
 
@@ -265,6 +268,50 @@
   s->intern_src += len;
 }
 
+/* Well-formedness checks on a closure */
+
+static bool well_formed_closure(value v)
+{
+  asize_t sz, envofs, i;
+  value cinfo;
+#define CHECK(b) if (! (b)) return false
+  sz = Wosize_val(v);
+  CHECK(sz >= 2);
+  // Check the first closure
+  cinfo = Closinfo_val(v);
+  CHECK(Is_long(cinfo));
+  envofs = Start_env_closinfo(cinfo);
+  CHECK(envofs >= 2 && envofs <= sz);
+  // Check the infix closures that can follow
+  i = 0;
+  while (1) {
+    // Skip to the next closure
+    int arity = Arity_closinfo(cinfo);
+    if (arity == 0 || arity == 1)
+      i += 3; // bytecode closure or native closure with arity 1
+    else
+      i += 4; // native closure with arity != 1: one extra entry points
+    if (i >= envofs) break;
+    if (i + 1 >= sz) return false;
+    // Check infix header and closure info
+    header_t h = (header_t) Field(v, i - 1);
+    CHECK(Tag_hd(h) == Infix_tag && Wosize_hd(h) == i);
+    cinfo = Field(v, i + 1);
+    CHECK(Is_long(cinfo));
+    CHECK(Start_env_closinfo(cinfo) + i == envofs);
+  }
+  i -= 1;
+  CHECK(i == envofs);
+  // Check that the environment part of the closure contains no code pointers
+  for (; i < sz; i++) {
+    value vi = Field(v, i);
+    if (Is_block(vi))
+      CHECK(caml_find_code_fragment_by_pc((char *) vi) == NULL);
+  }
+  return true;
+#undef CHECK
+}
+
 static void intern_init(struct caml_intern_state* s, const void * src,
                         uintnat len, void * input)
 {
@@ -298,6 +345,7 @@
     caml_stat_free(s->intern_obj_table);
     s->intern_obj_table = NULL;
     s->intern_num_objects = 0;
+    s->obj_counter = 0;
   }
   s->intern_dest = NULL;
   s->intern_dest_end = NULL;
@@ -427,20 +475,20 @@
 }
 
 /* Convenience macros for requesting operation on the stack */
-#define PushItem(s)                                                     \
-  do {                                                                  \
-    sp++;                                                               \
-    if (sp >= s->intern_stack_limit) sp = intern_resize_stack(s, sp);   \
+
+#define PushOperation(s,sp,_op,_dest,_arg)                                  \
+  do {                                                                      \
+    sp++;                                                                   \
+    if (sp >= s->intern_stack_limit) sp = intern_resize_stack(s, sp);       \
+    sp->op = _op;                                                           \
+    sp->dest = _dest;                                                       \
+    sp->arg = _arg;                                                         \
   } while(0)
 
-#define ReadItems(s,_dest,_n)                                           \
-  do {                                                                  \
-    if (_n > 0) {                                                       \
-      PushItem(s);                                                      \
-      sp->op = OReadItems;                                              \
-      sp->dest = _dest;                                                 \
-      sp->arg = _n;                                                     \
-    }                                                                   \
+#define ReadItems(s,sp,_dest,_n)                                            \
+  do {                                                                      \
+    CAMLassert((_n) > 0);                                                   \
+    PushOperation(s, sp, OReadItems, _dest, _n);                            \
   } while(0)
 
 static void intern_alloc_storage(struct caml_intern_state* s, mlsize_t whsize,
@@ -449,6 +497,7 @@
   mlsize_t wosize;
   value v;
 
+  s->obj_counter = 0;
   if (whsize == 0) {
     CAMLassert (s->intern_obj_table == NULL);
     return;
@@ -465,7 +514,6 @@
     CAMLassert (s->intern_dest == NULL);
   }
   s->intern_num_objects = num_objects;
-  s->obj_counter = 0;
   if (num_objects > 0) {
     s->intern_obj_table =
       (value *) caml_stat_calloc_noexc(num_objects, sizeof(value));
@@ -476,8 +524,6 @@
   } else {
     CAMLassert(s->intern_obj_table == NULL);
   }
-
-  return;
 }
 
 static value intern_alloc_obj(struct caml_intern_state* s, caml_domain_state* 
d,
@@ -530,19 +576,21 @@
   struct custom_operations * ops;
   char * codeptr;
   struct intern_item * sp;
+  enum intern_operation iop;
   caml_domain_state * d = Caml_state;
 
   sp = s->intern_stack;
 
   /* Initially let's try to read the first object from the stream */
-  ReadItems(s, dest, 1);
+  ReadItems(s, sp, dest, 1);
 
   /* The un-marshaler loop, the recursion is unrolled */
   while(sp != s->intern_stack) {
 
   /* Interpret next item on the stack */
+  iop = sp->op;
   dest = sp->dest;
-  switch (sp->op) {
+  switch (iop) {
   case OFreshOID:
     /* Refresh the object ID */
     /* but do not do it for predefined exception slots */
@@ -567,7 +615,16 @@
     /* Pop item and iterate */
     sp--;
     break;
+  case OCheckClosure:
+    /* Check that the closure is well-formed */
+    if (! well_formed_closure((value) dest)) {
+      intern_cleanup_failwith2(s, fun_name, "ill-formed function closure");
+    }
+    /* Pop item and iterate */
+    sp--;
+    break;
   case OReadItems:
+  case OReadItemsOrCodePointers:
     /* Pop item */
     sp->dest++;
     if (--(sp->arg) == 0) sp--;
@@ -579,27 +636,40 @@
       tag = code & 0xF;
       size = (code >> 4) & 0x7;
     read_block:
-      if (size == 0) {
+      if (CAMLunlikely(size == 0)) {
+        if (CAMLunlikely(tag >= Forcing_tag))
+          intern_cleanup_failwith2(s, fun_name, "bad atom tag");
         v = Atom(tag);
       } else {
         v = intern_alloc_obj (s, d, size, tag);
         intern_record_obj(s, v);
-        /* For objects, we need to freshen the oid */
-        if (tag == Object_tag) {
+        switch(tag) {
+        default:   // below Forcing_tag + Forcing_tag, Lazy_tag, Forward_tag
+          /* Read the contents of the block */
+          ReadItems(s, sp, &Field(v, 0), size);
+          break;
+        case Closure_tag:
+          /* For closures, we need to validate the closure after reading it */
+          PushOperation(s, sp, OCheckClosure, (value*) v, 0);
+          /* Code pointers are allowed in a closure block */
+          PushOperation(s, sp, OReadItemsOrCodePointers, &Field(v, 0), size);
+          break;
+        case Object_tag:
+          /* For objects, we need to freshen the oid */
           if (CAMLunlikely(size < 2))
             intern_cleanup_failwith2(s, fun_name, "bad object block");
           /* Request to read rest of the elements of the block */
-          ReadItems(s, &Field(v, 2), size - 2);
+          if (size > 2) ReadItems(s, sp, &Field(v, 2), size - 2);
           /* Request freshing OID */
-          PushItem(s);
-          sp->op = OFreshOID;
-          sp->dest = (value*) v;
-          sp->arg = 1;
+          PushOperation(s, sp, OFreshOID, (value*) v, 0);
           /* Finally read first two block elements: method table and old OID */
-          ReadItems(s, &Field(v, 0), 2);
-        } else
-          /* If it's not an object then read the contents of the block */
-          ReadItems(s, &Field(v, 0), size);
+          ReadItems(s, sp, &Field(v, 0), 2);
+          break;
+        case Infix_tag: case Cont_tag: case Abstract_tag: case String_tag:
+        case Double_tag: case Double_array_tag: case Custom_tag:
+          intern_cleanup_failwith2(s, fun_name, "bad block tag");
+          break;
+        }
       }
     } else {
       /* Small integer */
@@ -716,6 +786,8 @@
         goto read_double_array;
 #endif
       case CODE_CODEPOINTER:
+        if (iop != OReadItemsOrCodePointers)
+          intern_cleanup_failwith2(s, fun_name, "code pointer outside 
closure");
         ofs = read32u(s);
         readblock(s, digest, 16);
         codeptr = intern_resolve_code_pointer(digest, ofs);
@@ -736,11 +808,8 @@
       case CODE_INFIXPOINTER:
         ofs = read32u(s);
         /* Read a value to *dest, then offset *dest by ofs */
-        PushItem(s);
-        sp->dest = dest;
-        sp->op = OShift;
-        sp->arg = ofs;
-        ReadItems(s, dest, 1);
+        PushOperation(s, sp, OShift, dest, ofs);
+        ReadItems(s, sp, dest, 1);
         continue;  /* with next iteration of main loop, skipping *dest = v */
       case OLD_CODE_CUSTOM:
         intern_cleanup_failwith2(s, fun_name, "custom blocks serialized with "
@@ -783,6 +852,9 @@
           s->intern_src += 8;
         }
 #endif
+        if (expected_size > Bsize_wsize(Max_wosize - 1)) {
+          intern_cleanup_failwith2(s, fun_name, "custom block size too large");
+        }
         temp_size = 1 + (expected_size + sizeof(value) - 1) / sizeof(value);
         v = intern_alloc_obj(s, d, temp_size, Abstract_tag);
         Custom_ops_val(v) = ops;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude 
config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 
--exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh 
old/ocaml-5.5.1/runtime/runtime_events.c 
new/ocaml-5.5.2/runtime/runtime_events.c
--- old/ocaml-5.5.1/runtime/runtime_events.c    2026-09-04 13:16:34.000000000 
+0200
+++ new/ocaml-5.5.2/runtime/runtime_events.c    2026-10-23 13:52:23.000000000 
+0200
@@ -520,6 +520,28 @@
   /* account for header and timestamp (which are both uint64) */
   uint64_t length_with_header_ts = event_length + 2;
 
+  /* We must fatal error if the event cannot fit in the ring buffer.
+     Otherwise the loop below loops forever. In practice only the
+     alloc event can hit this, which is emitted by the instrumented
+     runtime. But users can also create arbitrarily sized events.
+     Closes #13335.
+
+     An event is only written whole, so one that would straddle the end of
+     the ring is preceded by padding and written at the start instead. The
+     loop below therefore has to fit the event plus that padding, and the
+     padding can be one word short of the event itself. Half the ring is the
+     largest event that always fits. Closes #15043. */
+  if (2 * length_with_header_ts > ring_size_words) {
+    int min_e = 0;
+    while ((1ULL << min_e) < 2 * length_with_header_ts) min_e++;
+    caml_fatal_error(
+        "runtime_events: event of %" PRIu64 " words does not fit in the ring "
+        "buffer (%d words, from OCAMLRUNPARAM=e=%" CAML_PRIuNAT "). "
+        "Use OCAMLRUNPARAM=e=%d or higher.",
+        length_with_header_ts, ring_size_words,
+        caml_params->runtime_events_log_wsize, min_e);
+  }
+
   /* there is a ring buffer (made up of header and data) for each domain */
   struct runtime_events_buffer_header *domain_ring_header =
       get_ring_buffer_by_domain_id(Caml_state->id);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude 
config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 
--exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh 
old/ocaml-5.5.1/stdlib/filename.ml new/ocaml-5.5.2/stdlib/filename.ml
--- old/ocaml-5.5.1/stdlib/filename.ml  2026-09-04 13:16:34.000000000 +0200
+++ new/ocaml-5.5.2/stdlib/filename.ml  2026-10-23 13:52:23.000000000 +0200
@@ -191,7 +191,9 @@
     String.iter
       (fun c ->
         match c with
-        | '(' | ')' | '!' | '^' | '%' | '\"' | '<' | '>' | '&' | '|' ->
+        | '\n' | '\r' ->
+            failwith ("Filename.quote_command: cannot escape newline in " ^ s)
+        | '(' | ')' | '!' | '^' | '%' | ':' | '\"' | '<' | '>' | '&' | '|' ->
             Buffer.add_char b '^'; Buffer.add_char b c
         | _ ->
             Buffer.add_char b c)
@@ -205,10 +207,13 @@
         String.map (function '/' -> '\\' | c -> c) f
       else f
     in
-    if String.exists (function '\"' | '%' -> true | _ -> false) f then
+    if String.exists (function
+              | '\n' | '\r' | '\"' | '%' -> true
+              | _ -> false) f then
       failwith ("Filename.quote_command: bad file name " ^ f)
     else if String.exists (function
-              | ' ' | '(' | ')' | '!' | '^' | '&' -> true
+              | ' ' | '\t' | '(' | ')' | '^' | '<' | '>' | '&' | '|' | '!'
+                  -> true
               | _ -> false) f then
       String.concat "" ["\""; f; "\""]
     else
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude 
config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 
--exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh 
old/ocaml-5.5.1/testsuite/tests/basic-more/pr15185.ml 
new/ocaml-5.5.2/testsuite/tests/basic-more/pr15185.ml
--- old/ocaml-5.5.1/testsuite/tests/basic-more/pr15185.ml       1970-01-01 
01:00:00.000000000 +0100
+++ new/ocaml-5.5.2/testsuite/tests/basic-more/pr15185.ml       2026-10-23 
13:52:23.000000000 +0200
@@ -0,0 +1,22 @@
+(* TEST
+   bytecode;
+*)
+
+(* This is a regression test for a miscompilation in the
+   pattern-matching compiler, which would only handle [x] values in
+   the interval [min_int; 3], despite the match being correctly
+   detected as partial.
+*)
+let[@warning "-partial-match"][@warning "-redundant-case"] f x y = match x, y 
with
+  | _, true -> 0
+  | (0 | 2), _ -> 1
+  | 3, true -> 2
+  | -1, _ -> 3
+
+(* The switcher then generates an exhaustive-switch instruction which
+   is passed below an input outside its input range, leading to
+   a segfault. *)
+let () =
+  match f 4 false with
+  | (n : int) -> ()
+  | exception Match_failure _ -> ()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude 
config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 
--exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh 
old/ocaml-5.5.1/testsuite/tests/lib-bigarray-file/mapfile.ml 
new/ocaml-5.5.2/testsuite/tests/lib-bigarray-file/mapfile.ml
--- old/ocaml-5.5.1/testsuite/tests/lib-bigarray-file/mapfile.ml        
2026-09-04 13:16:34.000000000 +0200
+++ new/ocaml-5.5.2/testsuite/tests/lib-bigarray-file/mapfile.ml        
2026-10-23 13:52:23.000000000 +0200
@@ -106,18 +106,43 @@
           Printf.eprintf "Unexpected error %s\n%!" (Unix.error_message err);
           false
       end;
-    Unix.close fd;
-    (* Invalid handle *)
+    (* Overflow in byte size *)
     test 2 true
       begin try
+        (* 2^64 bytes *)
+        let d = 0x1_0000 in
+        ignore (Unix.map_file fd char c_layout false [|d;d;d;d|]);
+        false
+      with
+      | Failure _ -> true
+      | Unix.Unix_error(err, _, _) ->
+          Printf.eprintf "Unexpected error %s\n%!" (Unix.error_message err);
+          false
+      end;
+    (* Overflow in file position *)
+    test 3 true
+      begin try
+        (* 2^63 bytes *)
+        let d = 0x1_0000 and e = 0x8000 in
+        ignore (Unix.map_file fd ~pos:10L char c_layout false [|e;d;d;d|]);
+        false
+      with
+      | Failure _ -> true
+      | Unix.Unix_error(err, _, _) ->
+          Printf.eprintf "Unexpected error %s\n%!" (Unix.error_message err);
+          false
+      end;
+    (* Invalid handle *)
+    Unix.close fd;
+    test 99 true
+      begin try
         ignore (Unix.map_file fd float64 c_layout true [|-1; 100|]); false
       with
       | Unix.Unix_error((Unix.EBADF|Unix.EINVAL), _, _) -> true
       | Unix.Unix_error(err, _, _) ->
           Printf.eprintf "Unexpected error %s\n%!" (Unix.error_message err);
           false
-      end
-
+      end;
   end;
   (* Force garbage collection of the mapped bigarrays above, otherwise
      Win32 doesn't let us erase the file.  Notice the begin...end above
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude 
config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 
--exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh 
old/ocaml-5.5.1/testsuite/tests/lib-bigarray-file/mapfile.reference 
new/ocaml-5.5.2/testsuite/tests/lib-bigarray-file/mapfile.reference
--- old/ocaml-5.5.1/testsuite/tests/lib-bigarray-file/mapfile.reference 
2026-09-04 13:16:34.000000000 +0200
+++ new/ocaml-5.5.2/testsuite/tests/lib-bigarray-file/mapfile.reference 
2026-10-23 13:52:23.000000000 +0200
@@ -2,4 +2,4 @@
 map_file
  1... 2... 3... 4...
 map_file errors
- 1... 2...
+ 1... 2... 3... 99...
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude 
config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 
--exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh 
old/ocaml-5.5.1/testsuite/tests/lib-filename/quotecommand.ml 
new/ocaml-5.5.2/testsuite/tests/lib-filename/quotecommand.ml
--- old/ocaml-5.5.1/testsuite/tests/lib-filename/quotecommand.ml        
2026-09-04 13:16:34.000000000 +0200
+++ new/ocaml-5.5.2/testsuite/tests/lib-filename/quotecommand.ml        
2026-10-23 13:52:23.000000000 +0200
@@ -159,7 +159,11 @@
     (fun () -> Filename.quote_command "true" ~stdout:"a%b" []);
   check_raises {|stdout "|}
     (fun () -> Filename.quote_command "true" ~stdout:{|a"b|} []);
+  check_raises "stdout LF"
+    (fun () -> Filename.quote_command "true" ~stdout:"a\nb" []);
   check_raises "program %"
     (fun () -> Filename.quote_command "a%b" []);
   check_raises {|program "|}
-    (fun () -> Filename.quote_command {|a"b|} [])
+    (fun () -> Filename.quote_command {|a"b|} []);
+  check_raises "program LF"
+    (fun () -> Filename.quote_command "a\nb" [])
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude 
config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 
--exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh 
old/ocaml-5.5.1/testsuite/tests/lib-filename/quotecommand.reference 
new/ocaml-5.5.2/testsuite/tests/lib-filename/quotecommand.reference
--- old/ocaml-5.5.1/testsuite/tests/lib-filename/quotecommand.reference 
2026-09-04 13:16:34.000000000 +0200
+++ new/ocaml-5.5.2/testsuite/tests/lib-filename/quotecommand.reference 
2026-10-23 13:52:23.000000000 +0200
@@ -82,5 +82,7 @@
 -------- Rejected (unquotable) characters
 stdout %: OK
 stdout ": OK
+stdout LF: OK
 program %: OK
 program ": OK
+program LF: OK
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude 
config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 
--exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh 
old/ocaml-5.5.1/testsuite/tests/lib-marshal/fuzzy.ml 
new/ocaml-5.5.2/testsuite/tests/lib-marshal/fuzzy.ml
--- old/ocaml-5.5.1/testsuite/tests/lib-marshal/fuzzy.ml        2026-09-04 
13:16:34.000000000 +0200
+++ new/ocaml-5.5.2/testsuite/tests/lib-marshal/fuzzy.ml        2026-10-23 
13:52:23.000000000 +0200
@@ -35,30 +35,22 @@
   Obj.repr (-1);
   Obj.repr 20000;
   Obj.repr 0x12345678;
-  Obj.repr bigint;
   Obj.repr "foo";
   Obj.repr longstring;
   Obj.repr 3.141592654;
   Obj.repr A;
   Obj.repr (B 1);
-  Obj.repr (C 2.718);
-  Obj.repr (D "hello");
-  Obj.repr (E 'l');
-  Obj.repr (F(B 1));
   Obj.repr (G(A, G(B 2, G(C 3.14, G(D "", E 'e')))));
-  Obj.repr (H(1, A));
-  Obj.repr (I(B 2, 1e-6));
   (let x = D "sharing" in
   let y = G(x, x) in
   let z = G(y, G(x, y)) in
   Obj.repr z);
-  Obj.repr [|1;2;3;4;5;6;7;8|];
+  Obj.repr [||];
+  Obj.repr [|1;2;3|];
   Obj.repr [|3.14; 2.718|];
   Obj.repr (closures());
   Obj.repr 0l;
-  Obj.repr 123456l;
   Obj.repr 0L;
-  (let i = Int64.of_string "123456789123456" in Obj.repr (i,i));
   Obj.repr (Failure "fail");
   Obj.repr Bigarray.(Array1.init int16_unsigned c_layout 5 (fun x -> 8*x))
 |]
@@ -69,26 +61,29 @@
   Out_channel.with_open_bin filename
     (fun oc -> Marshal.(to_channel oc (data()) [Closures]))
 
+(* Keep [x] alive *)
+
+let use_ignore x = ignore (Sys.opaque_identity x) [@@inline never]
+
 (* Try to unmarshal possibly malicious data.  Clean failure is success. *)
 
 let test ic =
   In_channel.set_binary_mode ic true;
-  begin try
-    ignore (Marshal.from_channel ic)
-  with Failure _ | Invalid_argument _ | Out_of_memory -> ()
-  end;
-  Gc.full_major()
+  try
+    let v : Obj.t = Marshal.from_channel ic in
+    Gc.full_major(); use_ignore v
+  with Failure _ | Invalid_argument _ | Out_of_memory ->
+    Gc.full_major()
 
 (* Same, but use Marshal.from_string instead *)
 
 let test_string ic =
   In_channel.set_binary_mode ic true;
   let s = In_channel.input_all ic in
-  begin try
-    ignore (Marshal.from_string s 0)
-  with Failure _ | Invalid_argument _ | Out_of_memory -> ()
-  end;
-  Gc.full_major()
+  try
+    let v : Obj.t = Marshal.from_string s 0 in
+    Gc.full_major(); use_ignore v
+  with Failure _ | Invalid_argument _ | Out_of_memory -> Gc.full_major()
 
 (* Internal fuzzing.  Rather naive. *)
 
@@ -116,10 +111,11 @@
     | _ (*3*) -> flip_one_bit b; flip_one_bit b
     end;
     begin try
-      ignore (Marshal.from_bytes b 0)
-    with Failure _ | Invalid_argument _ | Out_of_memory -> ()
-    end;
-    Gc.full_major()
+      let v : Obj.t = Marshal.from_bytes b 0 in
+      Gc.full_major(); use_ignore v
+    with Failure _ | Invalid_argument _ | Out_of_memory ->
+      Gc.full_major()
+    end
   done
 
 let fuzz1 () =
@@ -129,10 +125,11 @@
     for x = 0 to 255 do
       Bytes.set_uint8 b i x;
       begin try
-        ignore (Marshal.from_bytes b 0)
-      with Failure _ | Invalid_argument _ | Out_of_memory -> ()
-      end;
-      Gc.full_major()
+        let v : Obj.t = Marshal.from_bytes b 0 in
+        Gc.full_major(); use_ignore v
+      with Failure _ | Invalid_argument _ | Out_of_memory ->
+        Gc.full_major()
+      end
     done;
     Bytes.set_uint8 b i (String.get_uint8 d i)
   done
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude 
config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 
--exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh 
old/ocaml-5.5.1/testsuite/tests/lib-marshal/intext.ml 
new/ocaml-5.5.2/testsuite/tests/lib-marshal/intext.ml
--- old/ocaml-5.5.1/testsuite/tests/lib-marshal/intext.ml       2026-09-04 
13:16:34.000000000 +0200
+++ new/ocaml-5.5.2/testsuite/tests/lib-marshal/intext.ml       2026-10-23 
13:52:23.000000000 +0200
@@ -26,6 +26,10 @@
 let rec fib n =
   if n < 2 then 1 else fib(n-1) + fib(n-2)
 
+let lazy_u = lazy (fib 20)
+let lazy_e1 = Lazy.force (lazy (fib 10))
+let lazy_e2 = Lazy.force (lazy 3.14)
+
 let test_out ?(flags = []) filename =
   let oc = open_out_bin filename in
   Marshal.to_channel oc 1 flags;
@@ -72,6 +76,10 @@
     (Nativeint.shift_left (Nativeint.of_string "-123456789") 32) flags;
   let i = Int64.of_string "123456789123456" in
     Marshal.to_channel oc (i,i) flags;
+  Marshal.to_channel oc lazy_u (Marshal.Closures :: flags);
+  Marshal.to_channel oc lazy_e1 flags;
+  Marshal.to_channel oc lazy_e2 flags;
+  Marshal.to_channel oc [||] flags;
   close_out oc
 
 
@@ -155,6 +163,10 @@
   test 37 (i = Int64.of_string "123456789123456");
   test 38 (j = Int64.of_string "123456789123456");
   test 39 (i == j);
+  test 40 (Lazy.force (input_value ic) = fib 20);
+  test 41 (Lazy.force (input_value ic) = fib 10);
+  test 42 (Lazy.force (input_value ic) = 3.14);
+  test 43 (Array.length (input_value ic) = 0);
   close_in ic
 
 let test_string () =
@@ -548,6 +560,28 @@
   test 606 (even' 142 = true);
   test 607 (even' 142 = even 142)
 
+(* Test for infix pointers, with functions of arity >= 2 *)
+let test_infix2 () =
+  let t = true and
+      f = false in
+  let rec odd n z =
+    if n = z
+    then f
+    else even (n-1) z
+  and even n z =
+    if n = z
+    then t
+    else odd (n-1) z
+  in
+  let s = Marshal.to_string (odd, even) [Marshal.Closures] in
+  let (odd', even': (int -> int -> bool) * (int -> int -> bool))
+      = Marshal.from_string s 0 in
+  test 650 (odd' 41 0 = odd 41 0);
+  test 651 (odd' 142 0 = odd 142 0);
+  test 652 (odd' 142 3 = odd 142 3);
+  test 653 (even' 41 0 = even 41 0);
+  test 654 (even' 142 0 = even 142 0);
+  test 655 (even' 142 3 = even 142 3)
 
 let test_mutual_rec_regression () =
   (* this regression was reported by Cedric Pasteur in PR#5772 *)
@@ -629,6 +663,7 @@
     test_deep();
     test_objects();
     test_infix ();
+    test_infix2 ();
     test_mutual_rec_regression ();
     test_end_of_file_regression ();
     test_buggy_serialisers ();
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude 
config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 
--exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh 
old/ocaml-5.5.1/testsuite/tests/lib-marshal/intext.reference 
new/ocaml-5.5.2/testsuite/tests/lib-marshal/intext.reference
--- old/ocaml-5.5.1/testsuite/tests/lib-marshal/intext.reference        
2026-09-04 13:16:34.000000000 +0200
+++ new/ocaml-5.5.2/testsuite/tests/lib-marshal/intext.reference        
2026-10-23 13:52:23.000000000 +0200
@@ -38,6 +38,10 @@
 Test 37 passed.
 Test 38 passed.
 Test 39 passed.
+Test 40 passed.
+Test 41 passed.
+Test 42 passed.
+Test 43 passed.
 Default flags (again)
 Test 1 passed.
 Test 2 passed.
@@ -78,6 +82,10 @@
 Test 37 passed.
 Test 38 passed.
 Test 39 passed.
+Test 40 passed.
+Test 41 passed.
+Test 42 passed.
+Test 43 passed.
 Marshal.to_string
 Test 101 passed.
 Test 102 passed.
@@ -180,5 +188,11 @@
 Test 605 passed.
 Test 606 passed.
 Test 607 passed.
+Test 650 passed.
+Test 651 passed.
+Test 652 passed.
+Test 653 passed.
+Test 654 passed.
+Test 655 passed.
 Test 700 passed.
 Test 800 passed.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude 
config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 
--exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh 
old/ocaml-5.5.1/testsuite/tests/lib-runtime-events/test_big_event.ml 
new/ocaml-5.5.2/testsuite/tests/lib-runtime-events/test_big_event.ml
--- old/ocaml-5.5.1/testsuite/tests/lib-runtime-events/test_big_event.ml        
1970-01-01 01:00:00.000000000 +0100
+++ new/ocaml-5.5.2/testsuite/tests/lib-runtime-events/test_big_event.ml        
2026-10-23 13:52:23.000000000 +0200
@@ -0,0 +1,36 @@
+(* TEST
+ include runtime_events;
+ not-target-windows;
+ ocamlrunparam += ",e=8";
+ exit_status = "-6";
+ {
+   bytecode;
+ }{
+   native;
+ }
+*)
+
+(* An event is only ever written whole, so one that would straddle the end of
+   the ring is preceded by padding and written at the start instead. Making
+   room therefore has to account for the event plus that padding, which can be
+   one word short of the event itself, so anything larger than half the ring
+   can fail to fit however far the head is advanced. Before this was rejected
+   the loop in write_to_ring spun forever.
+
+   e=8 is a 256 word ring and the payload below is 128 words, which with the
+   header and timestamp is 131, comfortably over half. *)
+
+type Runtime_events.User.tag += Big
+
+let big_encoding =
+  let encode buf () = Bytes.fill buf 0 1024 'x'; 1024 in
+  let decode _ _ = () in
+  Runtime_events.Type.register ~encode ~decode
+
+let big = Runtime_events.User.register "big" Big big_encoding
+
+let () =
+  Runtime_events.start ();
+  Runtime_events.User.write big ();
+  (* Not reached: the write above must fatal error rather than hang. *)
+  print_string "wrote an event larger than half the ring\n"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude 
config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 
--exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh 
old/ocaml-5.5.1/testsuite/tests/lib-runtime-events/test_big_event.reference 
new/ocaml-5.5.2/testsuite/tests/lib-runtime-events/test_big_event.reference
--- old/ocaml-5.5.1/testsuite/tests/lib-runtime-events/test_big_event.reference 
1970-01-01 01:00:00.000000000 +0100
+++ new/ocaml-5.5.2/testsuite/tests/lib-runtime-events/test_big_event.reference 
2026-10-23 13:52:23.000000000 +0200
@@ -0,0 +1 @@
+Fatal error: runtime_events: event of 131 words does not fit in the ring 
buffer (256 words, from OCAMLRUNPARAM=e=8). Use OCAMLRUNPARAM=e=9 or higher.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude 
config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 
--exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh 
old/ocaml-5.5.1/testsuite/tests/lib-str/t01.ml 
new/ocaml-5.5.2/testsuite/tests/lib-str/t01.ml
--- old/ocaml-5.5.1/testsuite/tests/lib-str/t01.ml      2026-09-04 
13:16:34.000000000 +0200
+++ new/ocaml-5.5.2/testsuite/tests/lib-str/t01.ml      2026-10-23 
13:52:23.000000000 +0200
@@ -752,6 +752,29 @@
   test_partial_match r n "zorglub"
     [||];
 
+  start_test "Partial match for /\\([0-9]\\)[a-z]*!/";
+  let r = Str.regexp "\\([0-9]\\)[a-z]*!" in
+  let n = 1 in
+  test_partial_match r n ""
+    [|""; "~"|];
+  test_partial_match r n "0"
+    [|"0"; "0"|];
+  test_partial_match r n "0abc"
+    [|"0abc"; "0"|];
+  test_partial_match r n "0123"
+    [||];
+
+  start_test "Partial match for /\\(\\(a\\)b\\)+/";
+  let r = Str.regexp "\\(\\(a\\)b\\)+" in
+  let valid_group n s =
+    try ignore (Str.matched_group n s); true
+    with Not_found -> true | _ -> false in
+  (* Non-regression for OSEC-2026-21.  The exact values of the
+     captured groups are not well defined, but must be valid. *)
+  test true
+    (let s = "ab" in
+     Str.string_partial_match r s 0 && valid_group 1 s && valid_group 2 s);
+
   (** Replacement *)
   start_test "Global replacement";
   test (Str.global_replace (Str.regexp "[aeiou]") ".."
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude 
config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 
--exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh 
old/ocaml-5.5.1/testsuite/tests/lib-str/t01.reference 
new/ocaml-5.5.2/testsuite/tests/lib-str/t01.reference
--- old/ocaml-5.5.1/testsuite/tests/lib-str/t01.reference       2026-09-04 
13:16:34.000000000 +0200
+++ new/ocaml-5.5.2/testsuite/tests/lib-str/t01.reference       2026-10-23 
13:52:23.000000000 +0200
@@ -95,6 +95,10 @@
   ...
 Partial match for /\(partial\)\|\(match\)/
   ......
+Partial match for /\([0-9]\)[a-z]*!/
+  ....
+Partial match for /\(\(a\)b\)+/
+  .
 Global replacement
   ...
 First replacement
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude 
config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 
--exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh 
old/ocaml-5.5.1/testsuite/tests/lib-unix/win-createprocess/script.ml 
new/ocaml-5.5.2/testsuite/tests/lib-unix/win-createprocess/script.ml
--- old/ocaml-5.5.1/testsuite/tests/lib-unix/win-createprocess/script.ml        
1970-01-01 01:00:00.000000000 +0100
+++ new/ocaml-5.5.2/testsuite/tests/lib-unix/win-createprocess/script.ml        
2026-10-23 13:52:23.000000000 +0200
@@ -0,0 +1,42 @@
+(* TEST
+ include unix;
+ hasunix;
+ target-windows;
+ {
+   bytecode;
+ }{
+   native;
+ }
+*)
+
+(* Test argument passing and quoting to a .cmd/.bat script *)
+
+open Printf
+
+let create_file name contents =
+  Out_channel.with_open_text name (fun oc -> output_string oc contents)
+
+let run prog args =
+  try
+    let pid = Unix.(create_process prog args stdin stdout stderr) in
+    ignore (Unix.waitpid [] pid)
+  with Failure s ->
+    printf "Failure %s\n%!" s
+
+let chars = {xxx| !"#$%&'()*+,-./0:;<=>?@A[\]^_`a{|}~|xxx}
+
+let test_char arg =
+  printf "Testing \"%s\"\n%!" arg;
+  run ".\\echo.cmd" [|"echo.cmd"; arg; "X"|]
+
+let _ =
+  create_file "echo.cmd"
+    "@echo off\necho %2 \"%~1\"\n";
+  create_file "my (script).bat"
+    "@echo off\necho Hello world!\n";
+  String.iter
+    (fun c -> test_char (String.make 1 c))
+    chars;
+  printf "Extra tests\n%!";
+  run "./echo.cmd" [|"echo"; "1"; "2" |];
+  run "my (script).bat" [|"dir"|]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude 
config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 
--exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh 
old/ocaml-5.5.1/testsuite/tests/lib-unix/win-createprocess/script.reference 
new/ocaml-5.5.2/testsuite/tests/lib-unix/win-createprocess/script.reference
--- old/ocaml-5.5.1/testsuite/tests/lib-unix/win-createprocess/script.reference 
1970-01-01 01:00:00.000000000 +0100
+++ new/ocaml-5.5.2/testsuite/tests/lib-unix/win-createprocess/script.reference 
2026-10-23 13:52:23.000000000 +0200
@@ -0,0 +1,75 @@
+Testing " "
+X " "
+Testing "!"
+X "!"
+Testing """
+Failure Unix.create_process: unquotable argument to script: "
+Testing "#"
+X "#"
+Testing "$"
+X "$"
+Testing "%"
+Failure Unix.create_process: unquotable argument to script: %
+Testing "&"
+Failure Unix.create_process: unquotable argument to script: &
+Testing "'"
+X "'"
+Testing "("
+X "("
+Testing ")"
+X ")"
+Testing "*"
+X "*"
+Testing "+"
+X "+"
+Testing ","
+Failure Unix.create_process: unquotable argument to script: ,
+Testing "-"
+X "-"
+Testing "."
+X "."
+Testing "/"
+X "/"
+Testing "0"
+X "0"
+Testing ":"
+X ":"
+Testing ";"
+Failure Unix.create_process: unquotable argument to script: ;
+Testing "<"
+Failure Unix.create_process: unquotable argument to script: <
+Testing "="
+Failure Unix.create_process: unquotable argument to script: =
+Testing ">"
+Failure Unix.create_process: unquotable argument to script: >
+Testing "?"
+X "?"
+Testing "@"
+X "@"
+Testing "A"
+X "A"
+Testing "["
+X "["
+Testing "\"
+X "\"
+Testing "]"
+X "]"
+Testing "^"
+Failure Unix.create_process: unquotable argument to script: ^
+Testing "_"
+X "_"
+Testing "`"
+X "`"
+Testing "a"
+X "a"
+Testing "{"
+X "{"
+Testing "|"
+Failure Unix.create_process: unquotable argument to script: |
+Testing "}"
+X "}"
+Testing "~"
+X "~"
+Extra tests
+2 "1"
+Hello world!

Reply via email to