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-06-27 18:03:20 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/ocaml (Old) and /work/SRC/openSUSE:Factory/.ocaml.new.11887 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "ocaml" Sat Jun 27 18:03:20 2026 rev:94 rq:1361565 version:4.14.4 Changes: -------- --- /work/SRC/openSUSE:Factory/ocaml/ocaml.changes 2026-02-26 18:37:16.757173237 +0100 +++ /work/SRC/openSUSE:Factory/.ocaml.new.11887/ocaml.changes 2026-06-27 18:03:32.602831811 +0200 @@ -1,0 +2,7 @@ +Sat Jun 6 06:06:06 UTC 2026 - [email protected] + +- update to version 4.14.4 + See included Changes for benefits and breaking changes + (bsc#1260910 CVE-2026-34353) + +------------------------------------------------------------------- @@ -5,0 +13 @@ + (bsc#1258992 CVE-2026-28364) Old: ---- ocaml-4.14.3.tar.xz New: ---- ocaml-4.14.4.tar.xz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ ocaml.spec ++++++ --- /var/tmp/diff_new_pack.JlA7kz/_old 2026-06-27 18:03:33.510862250 +0200 +++ /var/tmp/diff_new_pack.JlA7kz/_new 2026-06-27 18:03:33.514862384 +0200 @@ -1,7 +1,7 @@ # # spec file for package ocaml # -# Copyright (c) 2025 SUSE LLC +# Copyright (c) 2026 SUSE LLC # Copyright (c) 2010 Andrew Psaltis <ampsaltis at gmail dot com> # Copyright (c) 2011 Andrew Psaltis <ampsaltis at gmail dot com> # @@ -42,7 +42,7 @@ %bcond_without suse_ocaml_use_rpm_license_macro Name: ocaml -Version: 4.14.3 +Version: 4.14.4 Release: 0 Summary: OCaml Compiler and Programming Environment %if %{with suse_ocaml_use_rpm_license_macro} ++++++ _service ++++++ --- /var/tmp/diff_new_pack.JlA7kz/_old 2026-06-27 18:03:33.554863725 +0200 +++ /var/tmp/diff_new_pack.JlA7kz/_new 2026-06-27 18:03:33.562863994 +0200 @@ -1,7 +1,7 @@ <services> <service name="tar_scm" mode="disabled"> <param name="filename">ocaml</param> - <param name="revision">ce529ce4255a8a057357647fe385c03b0132fdbe</param> + <param name="revision">2257629c205d0e1bc123cf048554979c74ae5410</param> <param name="scm">git</param> <param name="submodules">disable</param> <param name="url">https://github.com/ocaml/ocaml.git</param> ++++++ ocaml-4.14.3.tar.xz -> ocaml-4.14.4.tar.xz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ocaml-4.14.3/Changes new/ocaml-4.14.4/Changes --- old/ocaml-4.14.3/Changes 2026-02-17 14:20:42.000000000 +0100 +++ new/ocaml-4.14.4/Changes 2026-06-15 11:19:22.000000000 +0200 @@ -1,3 +1,49 @@ +OCaml 4.14 maintenance version +------------------------------- + +### Bug fixes: + + +OCaml 4.14.4 (15 June 2026) +------------------------------ + +### Build system: + +- #12372, #14572: Pass option -no-execute-only to the linker for OpenBSD >= 7.3 + so that code sections remain readable, as needed for closure marshaling. + Originally backported in 4.14.2, but the flag was accidentally not passed when + linking the .so versions of the OCaml runtime libraries or when linking .cmxs + files. + (Xavier Leroy and Anil Madhavapeddy, review by Anil Madhavapeddy and + Sébastien Hinderer) + +### Bug fixes: + +- #14599, #14606: on ARM64 platforms, ocamlopt was under-estimating + the sizes of some instructions. This could lead to overflows in + relative branch offsets, reported as errors by the assembler. + (Xavier Leroy, review by Vincent Laviron, report by Raphaël Proust) + +- #14607: Fix linking with libasmrun_shared.so on Risc-V (undefined symbol + declared riscv.o) + (David Allsopp, review by Nicolás Ojeda Bär) + +- #14661: Build dllthreads.so with pthreads flags (removed in #13018). For + normal programs there's no semantic difference, because ocamlrun and + ocamlc.opt are always linked with pthreads, but it was a regression to require + programs wishing to dlopen dllthreads.so to have already linked with pthreads + themselves. + (David Allsopp, review by Gabriel Scherer) + +- #14655, #14691, CVE-2026-34353, OSEC-2026-04: check for size overflow in + caml_ba_reshape + (Stephen Dolan, review by Xavier Leroy) + +- #14853, CVE-2026-41083, OSEC-2026-05: fix quoting of filenames passed to + Filename.quote_command on Windows. + (David Allsopp, report by Andrew Nesbitt, review by Florian Angeletti) + + OCaml 4.14.3 (17 February 2026) ------------------------------ @@ -36,7 +82,7 @@ demarshaling. (Benoît Vaugon, review by David Allsopp and Gabriel Scherer) -- private: robustify intern.c +- private, CVE-2026-28364, OSEC-2026-01: robustify intern.c (Xavier Leroy, review by Damien Doligez and Olivier Nicole) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ocaml-4.14.3/VERSION new/ocaml-4.14.4/VERSION --- old/ocaml-4.14.3/VERSION 2026-02-17 14:20:42.000000000 +0100 +++ new/ocaml-4.14.4/VERSION 2026-06-15 11:19:22.000000000 +0200 @@ -1,4 +1,4 @@ -4.14.3 +4.14.4 # 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' old/ocaml-4.14.3/asmcomp/arm64/emit.mlp new/ocaml-4.14.4/asmcomp/arm64/emit.mlp --- old/ocaml-4.14.3/asmcomp/arm64/emit.mlp 2026-02-17 14:20:42.000000000 +0100 +++ new/ocaml-4.14.4/asmcomp/arm64/emit.mlp 2026-06-15 11:19:22.000000000 +0200 @@ -440,6 +440,10 @@ let offset_pc_at_branch = 0 + let addsub_size n = + let m = abs n in + if m <= 0xFFF then 1 else if m land 0xFFF = 0 then 1 else 2 + let prologue_size f = (if initial_stack_offset f > 0 then 2 else 0) + (if f.fun_contains_calls then 1 else 0) @@ -473,8 +477,8 @@ | Lop (Ialloc { bytes = num_bytes; _ }) | Lop (Ispecific (Ifar_alloc { bytes = num_bytes; _ })) -> begin match num_bytes with - | 16 | 24 | 32 -> 1 - | _ -> 1 + num_instructions_for_intconst (Nativeint.of_int num_bytes) + | 16 | 24 | 32 -> 2 + | _ -> 2 + num_instructions_for_intconst (Nativeint.of_int num_bytes) end | Lop (Iintop (Icomp _)) -> 2 | Lop (Iintop_imm (Icomp _, _)) -> 2 @@ -487,6 +491,7 @@ | Lop (Iintop Imod) -> 2 | Lop (Iintop Imulh) -> 1 | Lop (Iintop _) -> 1 + | Lop (Iintop_imm ((Iadd|Isub), n)) -> addsub_size n | Lop (Iintop_imm _) -> 1 | Lop (Ifloatofint | Iintoffloat | Iabsf | Inegf | Ispecific Isqrtf) -> 1 | Lop (Iaddf | Isubf | Imulf | Idivf | Ispecific Inegmulf) -> 1 Binary files old/ocaml-4.14.3/boot/ocamlc and new/ocaml-4.14.4/boot/ocamlc differ Binary files old/ocaml-4.14.3/boot/ocamllex and new/ocaml-4.14.4/boot/ocamllex differ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ocaml-4.14.3/build-aux/ocaml_version.m4 new/ocaml-4.14.4/build-aux/ocaml_version.m4 --- old/ocaml-4.14.3/build-aux/ocaml_version.m4 2026-02-17 14:20:42.000000000 +0100 +++ new/ocaml-4.14.4/build-aux/ocaml_version.m4 2026-06-15 11:19:22.000000000 +0200 @@ -33,7 +33,7 @@ m4_define([OCAML__VERSION_MAJOR], [4]) m4_define([OCAML__VERSION_MINOR], [14]) -m4_define([OCAML__VERSION_PATCHLEVEL], [3]) +m4_define([OCAML__VERSION_PATCHLEVEL], [4]) # Note that the OCAML__VERSION_EXTRA string defined below is always empty # for officially-released versions of OCaml. m4_define([OCAML__VERSION_EXTRA], []) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ocaml-4.14.3/configure new/ocaml-4.14.4/configure --- old/ocaml-4.14.3/configure 2026-02-17 14:20:42.000000000 +0100 +++ new/ocaml-4.14.4/configure 2026-06-15 11:19:22.000000000 +0200 @@ -56,7 +56,7 @@ fi fi # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.69 for OCaml 4.14.3. +# Generated by GNU Autoconf 2.69 for OCaml 4.14.4. # # Report bugs to <[email protected]>. # @@ -646,8 +646,8 @@ # Identity of this package. PACKAGE_NAME='OCaml' PACKAGE_TARNAME='ocaml' -PACKAGE_VERSION='4.14.3' -PACKAGE_STRING='OCaml 4.14.3' +PACKAGE_VERSION='4.14.4' +PACKAGE_STRING='OCaml 4.14.4' PACKAGE_BUGREPORT='[email protected]' PACKAGE_URL='http://www.ocaml.org' @@ -1486,7 +1486,7 @@ # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures OCaml 4.14.3 to adapt to many kinds of systems. +\`configure' configures OCaml 4.14.4 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1552,7 +1552,7 @@ if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of OCaml 4.14.3:";; + short | recursive ) echo "Configuration of OCaml 4.14.4:";; esac cat <<\_ACEOF @@ -1718,7 +1718,7 @@ test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -OCaml configure 4.14.3 +OCaml configure 4.14.4 generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. @@ -2427,7 +2427,7 @@ This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by OCaml $as_me 4.14.3, which was +It was created by OCaml $as_me 4.14.4, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ @@ -2776,8 +2776,8 @@ -{ $as_echo "$as_me:${as_lineno-$LINENO}: Configuring OCaml version 4.14.3" >&5 -$as_echo "$as_me: Configuring OCaml version 4.14.3" >&6;} +{ $as_echo "$as_me:${as_lineno-$LINENO}: Configuring OCaml version 4.14.4" >&5 +$as_echo "$as_me: Configuring OCaml version 4.14.4" >&6;} # Configuration variables @@ -2853,7 +2853,7 @@ -VERSION=4.14.3 +VERSION=4.14.4 OCAML_DEVELOPMENT_VERSION=false @@ -2863,7 +2863,7 @@ OCAML_VERSION_MINOR=14 -OCAML_VERSION_PATCHLEVEL=3 +OCAML_VERSION_PATCHLEVEL=4 OCAML_VERSION_EXTRA= @@ -2986,15 +2986,15 @@ $as_echo "#define OCAML_VERSION_MINOR 14" >>confdefs.h -$as_echo "#define OCAML_VERSION_PATCHLEVEL 3" >>confdefs.h +$as_echo "#define OCAML_VERSION_PATCHLEVEL 4" >>confdefs.h $as_echo "#define OCAML_VERSION_ADDITIONAL \"\"" >>confdefs.h $as_echo "#define OCAML_VERSION_EXTRA \"\"" >>confdefs.h -$as_echo "#define OCAML_VERSION 41403" >>confdefs.h +$as_echo "#define OCAML_VERSION 41404" >>confdefs.h -$as_echo "#define OCAML_VERSION_STRING \"4.14.3\"" >>confdefs.h +$as_echo "#define OCAML_VERSION_STRING \"4.14.4\"" >>confdefs.h # Checks for system types @@ -14135,7 +14135,7 @@ esac case $host in #( *-*-openbsd7.[3-9]|*-*-openbsd[89].*) : - mkdll_flags="${mkdll_flags} -Wl,--no-execute-only" ;; #( + mksharedlib="${mksharedlib} -Wl,--no-execute-only" ;; #( *) : ;; esac @@ -18450,7 +18450,7 @@ # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by OCaml $as_me 4.14.3, which was +This file was extended by OCaml $as_me 4.14.4, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -18517,7 +18517,7 @@ cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ -OCaml config.status 4.14.3 +OCaml config.status 4.14.4 configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ocaml-4.14.3/configure.ac new/ocaml-4.14.4/configure.ac --- old/ocaml-4.14.3/configure.ac 2026-02-17 14:20:42.000000000 +0100 +++ new/ocaml-4.14.4/configure.ac 2026-06-15 11:19:22.000000000 +0200 @@ -993,7 +993,7 @@ [mksharedlib="$CC -shared \$(LDFLAGS)"]) AS_CASE([$host], [[*-*-openbsd7.[3-9]|*-*-openbsd[89].*]], - [mkdll_flags="${mkdll_flags} -Wl,--no-execute-only"]) + [mksharedlib="${mksharedlib} -Wl,--no-execute-only"]) oc_ldflags="$oc_ldflags -Wl,-E" rpath="-Wl,-rpath," mksharedlibrpath="-Wl,-rpath," diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ocaml-4.14.3/ocaml-variants.opam new/ocaml-4.14.4/ocaml-variants.opam --- old/ocaml-4.14.3/ocaml-variants.opam 2026-02-17 14:20:42.000000000 +0100 +++ new/ocaml-4.14.4/ocaml-variants.opam 2026-06-15 11:19:22.000000000 +0200 @@ -1,7 +1,7 @@ opam-version: "2.0" -version: "4.14.3" +version: "4.14.4" license: "LGPL-2.1-or-later WITH OCaml-LGPL-linking-exception" -synopsis: "Official OCaml 4.14.3 release" +synopsis: "Official release of OCaml 4.14.4" maintainer: "[email protected]" authors: [ "Xavier Leroy" @@ -14,8 +14,8 @@ homepage: "https://github.com/ocaml/ocaml/" bug-reports: "https://github.com/ocaml/ocaml/issues" depends: [ - # This is OCaml 4.14.3 - "ocaml" {= "4.14.3" & post} + # This is OCaml 4.14.4 + "ocaml" {= "4.14.4" & post} # General base- packages "base-unix" {post} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ocaml-4.14.3/otherlibs/systhreads/Makefile new/ocaml-4.14.4/otherlibs/systhreads/Makefile --- old/ocaml-4.14.3/otherlibs/systhreads/Makefile 2026-02-17 14:20:42.000000000 +0100 +++ new/ocaml-4.14.4/otherlibs/systhreads/Makefile 2026-06-15 11:19:22.000000000 +0200 @@ -65,8 +65,10 @@ allopt: lib$(LIBNAME)nat.$(A) $(LIBNAME).cmxa $(CMIFILES) +# Bytecode programs always link with pthread libraries, but the dependency +# should still be recorded in the DLL. lib$(LIBNAME).$(A): $(BYTECODE_C_OBJS) - $(MKLIB_CMD) -o $(LIBNAME) $(BYTECODE_C_OBJS) + $(MKLIB_CMD) -o $(LIBNAME) $(BYTECODE_C_OBJS) $(PTHREAD_LIBS) lib$(LIBNAME)nat.$(A): $(NATIVECODE_C_OBJS) $(MKLIB_CMD) -o $(LIBNAME)nat $^ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ocaml-4.14.3/runtime/bigarray.c new/ocaml-4.14.4/runtime/bigarray.c --- old/ocaml-4.14.3/runtime/bigarray.c 2026-02-17 14:20:42.000000000 +0100 +++ new/ocaml-4.14.4/runtime/bigarray.c 2026-06-15 11:19:22.000000000 +0200 @@ -1219,7 +1219,9 @@ dim[i] = Long_val(Field(vdim, i)); if (dim[i] < 0) caml_invalid_argument("Bigarray.reshape: negative dimension"); - num_elts *= dim[i]; + if (caml_umul_overflow(num_elts, (uintnat)dim[i], &num_elts)) + /* Since the old dims didn't overflow, an overflow must be a mismatch */ + caml_invalid_argument("Bigarray.reshape: size mismatch"); } /* Check that sizes agree */ if (num_elts != caml_ba_num_elts(b)) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ocaml-4.14.3/runtime/riscv.S new/ocaml-4.14.4/runtime/riscv.S --- old/ocaml-4.14.3/runtime/riscv.S 2026-02-17 14:20:42.000000000 +0100 +++ new/ocaml-4.14.4/runtime/riscv.S 2026-06-15 11:19:22.000000000 +0200 @@ -245,9 +245,6 @@ j 1b END_FUNCTION(caml_raise_exn) - .globl caml_reraise_exn - .type caml_reraise_exn, @function - /* Raise an exception from C */ FUNCTION(caml_raise_exception) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ocaml-4.14.3/stdlib/filename.ml new/ocaml-4.14.4/stdlib/filename.ml --- old/ocaml-4.14.3/stdlib/filename.ml 2026-02-17 14:20:42.000000000 +0100 +++ new/ocaml-4.14.4/stdlib/filename.ml 2026-06-15 11:19:22.000000000 +0200 @@ -193,13 +193,13 @@ protect it against the processing performed by the C runtime system, then cmd.exe's special characters are escaped with '^', using the "quote_cmd" function below. For more details, see - https://blogs.msdn.microsoft.com/twistylittlepassagesallalike/2011/04/23 + https://web.archive.org/web/20251122022701/https://learn.microsoft.com/en-us/archive/blogs/twistylittlepassagesallalike/everyone-quotes-command-line-arguments-the-wrong-way 2- The command and the redirection files, if any, must be double-quoted - in case they contain spaces. This quoting is interpreted by cmd.exe, - not by the C runtime system, hence the "quote" function above - cannot be used. The two characters we don't know how to quote - inside a double-quoted cmd.exe string are double-quote and percent. - We just fail if the command name or the redirection file names + if they contain any of the special characters which are valid in filenames. + This quoting is interpreted by cmd.exe, not by the C runtime system, hence + the "quote" function above cannot be used. The two characters we don't know + how to quote inside a double-quoted cmd.exe string are double-quote and + percent. We just fail if the command name or the redirection file names contain a double quote (not allowed in Windows file names, anyway) or a percent. See function "quote_cmd_filename" below. 3- The whole string passed to Sys.command is then enclosed in double @@ -221,8 +221,10 @@ let quote_cmd_filename f = if String.contains f '\"' || String.contains f '%' then failwith ("Filename.quote_command: bad file name " ^ f) - else if String.contains f ' ' then - "\"" ^ f ^ "\"" + else if String.exists (function + | ' ' | '(' | ')' | '!' | '^' | '&' -> true + | _ -> false) f then + String.concat "" ["\""; f; "\""] else f (* Redirections in cmd.exe: see https://ss64.com/nt/syntax-redirection.html diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ocaml-4.14.3/testsuite/tests/lib-bigarray/reshape_overflow.ml new/ocaml-4.14.4/testsuite/tests/lib-bigarray/reshape_overflow.ml --- old/ocaml-4.14.3/testsuite/tests/lib-bigarray/reshape_overflow.ml 1970-01-01 01:00:00.000000000 +0100 +++ new/ocaml-4.14.4/testsuite/tests/lib-bigarray/reshape_overflow.ml 2026-06-15 11:19:22.000000000 +0200 @@ -0,0 +1,12 @@ +(* TEST *) +open Printf +open Bigarray + +let () = + let ba = Array1.create int c_layout 0 in + match reshape (genarray_of_array1 ba) (Array.init 8 (fun _ -> 1 lsl 16)) with + | ba -> + printf "out of bounds read: %d\n" + (Genarray.get ba (Array.init 8 (fun _ -> 10))) + | exception exn -> + printf "ok: %s\n" (Printexc.to_string exn) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ocaml-4.14.3/testsuite/tests/lib-bigarray/reshape_overflow.reference new/ocaml-4.14.4/testsuite/tests/lib-bigarray/reshape_overflow.reference --- old/ocaml-4.14.3/testsuite/tests/lib-bigarray/reshape_overflow.reference 1970-01-01 01:00:00.000000000 +0100 +++ new/ocaml-4.14.4/testsuite/tests/lib-bigarray/reshape_overflow.reference 2026-06-15 11:19:22.000000000 +0200 @@ -0,0 +1 @@ +ok: Invalid_argument("Bigarray.reshape: size mismatch") diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ocaml-4.14.3/testsuite/tests/lib-filename/quotecommand.ml new/ocaml-4.14.4/testsuite/tests/lib-filename/quotecommand.ml --- old/ocaml-4.14.3/testsuite/tests/lib-filename/quotecommand.ml 2026-02-17 14:20:42.000000000 +0100 +++ new/ocaml-4.14.4/testsuite/tests/lib-filename/quotecommand.ml 2026-06-15 11:19:22.000000000 +0200 @@ -47,23 +47,28 @@ close_in ic; close_out oc -let cat_file f = - let ic = open_in f in - copy_channels ic stdout; - close_in ic +let cat_and_rm_file f = + match open_in f with + | ic -> + copy_channels ic stdout; + close_in ic; + Sys.remove f + | exception Sys_error _ -> + printf "Could not open %S\n" f let myecho = Filename.concat Filename.current_dir_name "my echo.exe" -let run ?stdin ?stdout ?stderr args = +let run ?(prog=myecho) ?stdin ?stdout ?stderr args = flush Stdlib.stdout; let rc = - Sys.command (Filename.quote_command myecho ?stdin ?stdout ?stderr args) in + Sys.command (Filename.quote_command prog ?stdin ?stdout ?stderr args) in if rc > 0 then begin printf "!!! my echo failed\n"; exit 2 end + let _ = copy_file "myecho.exe" "my echo.exe"; printf "-------- Spaces\n"; @@ -88,17 +93,77 @@ ["Exceptur sint"; "-err"; "occaecat"; "cupidatat"; "-out"; "non proident"; "-err"; "sunt in culpa"]; printf "-- stderr:\n"; - cat_file "my 'file'.tmp"; - Sys.remove "my 'file'.tmp"; + cat_and_rm_file "my 'file'.tmp"; printf "-------- Output and error redirections (different files)\n"; run ~stdout:"my stdout.tmp" ~stderr:"my stderr.tmp" ["qui officia"; "-err"; "deserunt"; "mollit"; "-out"; "anim id est"; "-err"; "laborum."]; - printf "-- stdout:\n"; cat_file "my stdout.tmp"; Sys.remove "my stdout.tmp"; - printf "-- stderr:\n"; cat_file "my stderr.tmp"; Sys.remove "my stderr.tmp"; + printf "-- stdout:\n"; cat_and_rm_file "my stdout.tmp"; + printf "-- stderr:\n"; cat_and_rm_file "my stderr.tmp"; printf "-------- Output and error redirections (same file)\n"; run ~stdout:"my file.tmp" ~stderr:"my file.tmp" ["Duis aute"; "irure dolor"; "-err"; "in reprehenderit"; "in voluptate"; "-out"; "velit esse cillum"; "-err"; "dolore"]; - cat_file "my file.tmp"; Sys.remove "my file.tmp"; + cat_and_rm_file "my file.tmp"; Sys.remove "my echo.exe" + +let _ = + printf "-------- Forward slashes in program position\n"; + run ~prog:"./myecho.exe" ["alea iacta est"] + +let echo_exe = "./myecho.exe" + +(* The program name and the redirection files go through quote_cmd_filename, + which must double-quote cmd.exe metacharacters that are legal in a Windows + file name (& ( ) ^), not just spaces. These check the right program is + found and the right (literally named) file is written -- i.e. both that no + command is injected and that the result is correct. *) + +let _ = + printf "-------- Metacharacters in program name\n"; + List.iter (fun name -> + let prog = Filename.concat Filename.current_dir_name name in + copy_file "myecho.exe" name; + printf "-- %s\n" name; + run ~prog ["per aspera"; "ad astra"]; + Sys.remove name) + ["my&echo.exe"; "my(echo).exe"; "my(echo.exe"; "my)echo.exe"; "my^echo.exe"; "my!echo.exe"] + +let _ = + printf "-------- Redirection to names with metacharacters\n"; + List.iter (fun fn -> + run ~prog:echo_exe ~stdout:fn ["lux et veritas"]; + printf "-- %s:\n" fn; + cat_and_rm_file fn) + ["out&put.tmp"; "out(put).tmp"; "out(put.tmp"; "out)put.tmp"; "out^put.tmp"; "out!put.tmp"; "a & b.tmp"] + +(* Arguments go through quote then quote_cmd. Check that variable expansion is + suppressed and that trailing backslashes survive the C-runtime quoting. *) +let _ = + printf "-------- Adversarial arguments\n"; + run ~prog:echo_exe ["%PATH%"; {|"&whoami&"|}; {|C:\Program Files\|}; + {|a\|}; {|a\\|}; ""] + +(* The two characters quote_cmd_filename cannot quote (double-quote and %) must + be rejected with Failure, in the program name and in any redirection file. *) +let check_raises descr f = + let raised_failure = + match f () with + | _ -> false + | exception Failure _ -> true + in + if raised_failure = Sys.win32 then + printf "%s: OK\n" descr + else + printf "%s: ERROR\n" descr + +let _ = + printf "-------- Rejected (unquotable) characters\n"; + check_raises "stdout %" + (fun () -> Filename.quote_command "true" ~stdout:"a%b" []); + check_raises {|stdout "|} + (fun () -> Filename.quote_command "true" ~stdout:{|a"b|} []); + check_raises "program %" + (fun () -> Filename.quote_command "a%b" []); + check_raises {|program "|} + (fun () -> Filename.quote_command {|a"b|} []) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ocaml-4.14.3/testsuite/tests/lib-filename/quotecommand.reference new/ocaml-4.14.4/testsuite/tests/lib-filename/quotecommand.reference --- old/ocaml-4.14.3/testsuite/tests/lib-filename/quotecommand.reference 2026-02-17 14:20:42.000000000 +0100 +++ new/ocaml-4.14.4/testsuite/tests/lib-filename/quotecommand.reference 2026-06-15 11:19:22.000000000 +0200 @@ -36,3 +36,51 @@ argv[5] = {|in voluptate|} argv[7] = {|velit esse cillum|} argv[9] = {|dolore|} +-------- Forward slashes in program position +argv[1] = {|alea iacta est|} +-------- Metacharacters in program name +-- my&echo.exe +argv[1] = {|per aspera|} +argv[2] = {|ad astra|} +-- my(echo).exe +argv[1] = {|per aspera|} +argv[2] = {|ad astra|} +-- my(echo.exe +argv[1] = {|per aspera|} +argv[2] = {|ad astra|} +-- my)echo.exe +argv[1] = {|per aspera|} +argv[2] = {|ad astra|} +-- my^echo.exe +argv[1] = {|per aspera|} +argv[2] = {|ad astra|} +-- my!echo.exe +argv[1] = {|per aspera|} +argv[2] = {|ad astra|} +-------- Redirection to names with metacharacters +-- out&put.tmp: +argv[1] = {|lux et veritas|} +-- out(put).tmp: +argv[1] = {|lux et veritas|} +-- out(put.tmp: +argv[1] = {|lux et veritas|} +-- out)put.tmp: +argv[1] = {|lux et veritas|} +-- out^put.tmp: +argv[1] = {|lux et veritas|} +-- out!put.tmp: +argv[1] = {|lux et veritas|} +-- a & b.tmp: +argv[1] = {|lux et veritas|} +-------- Adversarial arguments +argv[1] = {|%PATH%|} +argv[2] = {|"&whoami&"|} +argv[3] = {|C:\Program Files\|} +argv[4] = {|a\|} +argv[5] = {|a\\|} +argv[6] = {||} +-------- Rejected (unquotable) characters +stdout %: OK +stdout ": OK +program %: OK +program ": OK diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ocaml-4.14.3/testsuite/tests/lib-filename/windows.ml new/ocaml-4.14.4/testsuite/tests/lib-filename/windows.ml --- old/ocaml-4.14.3/testsuite/tests/lib-filename/windows.ml 1970-01-01 01:00:00.000000000 +0100 +++ new/ocaml-4.14.4/testsuite/tests/lib-filename/windows.ml 2026-06-15 11:19:22.000000000 +0200 @@ -0,0 +1,50 @@ +(* TEST + target-windows; + { + bytecode; + }{ + native; + } +*) + +(* Adversarial tests for Filename.quote_command: a hostile string supplied as + a redirection target or program name must not be able to smuggle an extra + command past cmd.exe. + + The cmd.exe metacharacters split in two, according to whether they are legal + in a Windows file name: + + - Legal in a file name (& ( ) ^): a correctly quoted target becomes a real + (oddly named) file, so we can actually run "true" with the redirection and + confirm it executes (Result 0) instead of the injected "false" (which + would give a non-zero code). The payloads contain no spaces, so that the + pre-fix code -- which double-quoted only when a space was present -- does + not neutralise them by accident. + + - Illegal in a file name (| < >): such a string can never name a real file, + so a correctly quoted target can only ever make cmd.exe fail, never + execute. Running it would just compare cmd.exe's locale-dependent error + text, so instead we pin the constructed command line and check the target + is wrapped in double quotes. + + true/false are the POSIX commands on the PATH (the testsuite runs under + Cygwin). *) + +let remove f = try Sys.remove f with Sys_error _ -> () + +(* Run the redirection and report the exit code. A correctly quoted target is + a real file, so "true" runs and the code is 0. *) +let run_probe label ?stdin ?stdout ?stderr () = + let cmd = Filename.quote_command "true" ?stdin ?stdout ?stderr [] in + let rc = Sys.command cmd in + List.iter (function Some f -> remove f | None -> ()) [stdin; stdout; stderr]; + Printf.printf "%s: %S -> %d\n" label cmd rc + +let () = + print_string "==== Executable (legal file name) targets, must not inject\n"; + run_probe "stdout &" ~stdout:"out&false" (); + run_probe "stdout &&" ~stdout:"out&&false" (); + run_probe "stdout ()" ~stdout:"out(false)" (); + run_probe "stdout (" ~stdout:"out(false)" (); + run_probe "stdout )" ~stdout:"out(false)" (); + run_probe "stderr &" ~stderr:"err&false" (); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ocaml-4.14.3/testsuite/tests/lib-filename/windows.reference new/ocaml-4.14.4/testsuite/tests/lib-filename/windows.reference --- old/ocaml-4.14.3/testsuite/tests/lib-filename/windows.reference 1970-01-01 01:00:00.000000000 +0100 +++ new/ocaml-4.14.4/testsuite/tests/lib-filename/windows.reference 2026-06-15 11:19:22.000000000 +0200 @@ -0,0 +1,7 @@ +==== Executable (legal file name) targets, must not inject +stdout &: "\"true >\"out&false\"\"" -> 0 +stdout &&: "\"true >\"out&&false\"\"" -> 0 +stdout (): "\"true >\"out(false)\"\"" -> 0 +stdout (: "\"true >\"out(false)\"\"" -> 0 +stdout ): "\"true >\"out(false)\"\"" -> 0 +stderr &: "\"true 2>\"err&false\"\"" -> 0 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ocaml-4.14.3/tools/ci/inria/main new/ocaml-4.14.4/tools/ci/inria/main --- old/ocaml-4.14.3/tools/ci/inria/main 2026-02-17 14:20:42.000000000 +0100 +++ new/ocaml-4.14.4/tools/ci/inria/main 2026-06-15 11:19:22.000000000 +0200 @@ -262,6 +262,8 @@ main_build() { eval ./configure "$CCOMP" $build $host --prefix='$instdir' $confoptions + grep -q '^NATIVE_COMPILER=false' Makefile.config && make_native=false + if $bootstrap; then $make $jobs --warn-undefined-variables core $make $jobs --warn-undefined-variables coreboot diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ocaml-4.14.3/tools/ci/inria/sanitizers/script new/ocaml-4.14.4/tools/ci/inria/sanitizers/script --- old/ocaml-4.14.3/tools/ci/inria/sanitizers/script 2026-02-17 14:20:42.000000000 +0100 +++ new/ocaml-4.14.4/tools/ci/inria/sanitizers/script 2026-06-15 11:19:22.000000000 +0200 @@ -46,15 +46,21 @@ run_testsuite="$make -C testsuite all" fi +# Figure out which version of llvm/clang to use +llvm_version=$(clang -dumpversion | cut -d . -f 1) +clang=clang-${llvm_version} +llvm_bin_dir=/usr/lib/llvm-${llvm_version}/bin + # A tool that makes error backtraces nicer -# Need to pick the one that matches clang-14 and is named "llvm-symbolizer" -# (/usr/bin/llvm-symbolizer-9 doesn't work, that would be too easy) -export ASAN_SYMBOLIZER_PATH=/usr/lib/llvm-14/bin/llvm-symbolizer +# Need to pick the one that matches clang's version and is named +# "llvm-symbolizer" (/usr/bin/llvm-symbolizer-xx doesn't work, +# that would be too easy) +export ASAN_SYMBOLIZER_PATH=${llvm_bin_dir}/llvm-symbolizer export TSAN_SYMBOLIZER_PATH="$ASAN_SYMBOLIZER_PATH" ######################################################################### -echo "======== clang, address sanitizer, UB sanitizer ==========" +echo "======== clang ${llvm_version}, address sanitizer, UB sanitizer ========" git clean -q -f -d -x @@ -79,8 +85,9 @@ # Don't optimize too much to get better backtraces of errors ./configure \ - CC=clang-14 \ + CC=$clang \ CFLAGS="-O1 -fno-omit-frame-pointer $sanitizers" \ + LDFLAGS="$sanitizers" \ --disable-stdlib-manpages --enable-dependency-generation # Build the system. We want to check for memory leaks, hence @@ -105,7 +112,7 @@ ######################################################################### -echo "======== clang, thread sanitizer ==========" +echo "======== clang ${llvm_version}, thread sanitizer ========" git clean -q -f -d -x @@ -113,7 +120,7 @@ # Don't optimize too much to get better backtraces of errors ./configure \ - CC=clang-14 \ + CC=$clang \ CFLAGS="-O1 -fno-omit-frame-pointer -fsanitize=thread" \ --disable-stdlib-manpages --enable-dependency-generation @@ -142,7 +149,7 @@ # Some alarms are reported that look like false positive # and are impossible to debug. -# echo "======== clang 6.0, memory sanitizer ==========" +# echo "======== clang ${llvm_version}, memory sanitizer ========" # git clean -q -f -d -x @@ -153,8 +160,9 @@ # # Don't optimize at all to get better backtraces of errors # ./configure \ -# CC=clang-6 \ +# CC=$clang \ # CFLAGS="-O0 -g -fno-omit-frame-pointer -fsanitize=memory" \ +# LDFLAGS="-fsanitize=memory" \ # --disable-native-compiler # # A tool that makes error backtraces nicer # # Need to pick the one that matches clang-6.0
