Compare commits

..

No commits in common. "ubuntu/jammy-updates" and "upstream/2.72.4" have entirely different histories.

91 changed files with 0 additions and 18333 deletions

6586
debian/changelog vendored

File diff suppressed because it is too large Load diff

6
debian/clean vendored
View file

@ -1,6 +0,0 @@
debian/cross.txt
debian/cross.txt.in
debian/libglib2.0-0.triggers
debian/libglib2.0-0.postinst
debian/libglib2.0-0.postrm
gio/gdbus-2.0/codegen/*.pyc

View file

@ -1,216 +0,0 @@
#!/bin/dash
# (This script requires either dash or bash due to its use of test -ef.)
# Copyright 2020 Collabora Ltd.
# SPDX-License-Identifier: MIT
# (see "Expat" paragraph in debian/copyright)
set -eu
# global
bug_ref=911225
force=
me="$0"
need_ldconfig=
really=yes
verbose=
debug () {
[ -z "$verbose" ] || echo "DEBUG: $me: $*" >&2
}
warning () {
echo "WARNING: $me: $*" >&2
}
usage () {
local status="${1:-2}"
if [ "$status" -gt 0 ]; then
exec >&2
fi
cat <<EOF
Usage: $me [OPTIONS] MULTIARCH SONAME...
Clean up unmanaged copies of SONAME that might still exist
in /lib/MULTIARCH after upgrading to a version that is in
/usr/lib/MULTIARCH. On non-merged-/usr systems, because /lib/MULTIARCH
is higher-precedence than /usr/lib/MULTIARCH, that can result in the
old version continuing to be used, breaking versioned dependencies.
See #911225, #949395 and related bugs.
Options:
--bug-ref=BUG Mention BUG in log messages
--dry-run Don't remove the files, just report
--force Run even if the system is merged-/usr
--verbose Be more verbose
EOF
exit "$status"
}
do_soname () {
local multiarch="$1"
local soname="$2"
local impl
local owner
local removal="/lib/$multiarch/removed-by-upgrade-bug$bug_ref"
local found_one=
# We had better not remove the only copy of $soname. This script is
# for the situation where it moved from /lib/MULTIARCH/SONAME to
# /usr/lib/MULTIARCH/SONAME, so fail in all other cases.
if ! [ -e "/usr/lib/$multiarch/$soname" ]; then
warning "/usr/lib/$multiarch/$soname does not exist"
return 1
fi
# Safety-catch against problems with dpkg-query: if no package is said
# to own the new version of the library, fail early.
if owner=$(dpkg-query -S "/usr/lib/$multiarch/$soname"); then
owner="${owner%%:*}"
debug "/usr/lib/$multiarch/$soname is owned by $owner"
else
warning "/usr/lib/$multiarch/$soname is not owned by a package?"
return 1
fi
for impl in "/lib/$multiarch/$soname".*; do
if ! [ -e "$impl" ]; then
continue
fi
found_one=yes
if owner=$(dpkg-query -S "$impl"); then
owner="${owner%%:*}"
warning "$impl is owned by $owner, not deleting"
continue
fi
if [ "/usr$impl" -ef "$impl" ] && owner=$(dpkg-query -S "/usr$impl"); then
owner="${owner%%:*}"
warning "/usr$impl is owned by $owner, not deleting"
continue
fi
warning "$impl is not owned by any package"
warning "Related files:"
ls -il \
"/lib/$multiarch/$soname" \
"/lib/$multiarch/$soname".* \
"/usr/lib/$multiarch/$soname" \
"/usr/lib/$multiarch/$soname".* \
>&2 || :
if [ -n "$really" ]; then
warning "Moving $impl into $removal"
install -d "$removal"
rm -f "$removal/${impl##*/}"
mv "$impl" "$removal/."
else
warning "Not moving $impl into $removal (--dry-run)"
fi
echo >&2
need_ldconfig=yes
done
if [ -z "$found_one" ]; then
debug "No stray files found at /lib/$multiarch/$soname.*"
fi
}
main () {
local getopt_temp
local multiarch
local soname
getopt_temp="help"
getopt_temp="$getopt_temp,bug-ref:"
getopt_temp="$getopt_temp,dry-run"
getopt_temp="$getopt_temp,force"
getopt_temp="$getopt_temp,verbose"
getopt_temp="$(getopt -o '' --long "$getopt_temp" -n "$me" -- "$@")"
eval "set -- $getopt_temp"
while [ "$#" -gt 0 ]
do
case "$1" in
(--dry-run)
really=
verbose=yes
shift
;;
(--bug-ref)
bug_ref="$2"
shift 2
;;
(--force)
force=yes
shift
;;
(--help)
usage 0
;;
(--verbose)
verbose=yes
shift
;;
(--)
shift
break
;;
(-*)
warning "Unknown option: $1"
usage 2
;;
(*)
break
;;
esac
done
if [ "$#" -lt 2 ]; then
warning "A multiarch tuple and at least one SONAME are required"
usage 2
fi
multiarch="$1"
shift
if [ -n "$force" ]; then
debug "Using force"
elif [ "/usr/lib/$multiarch" -ef "/lib/$multiarch" ]; then
# On a merged-/usr system, a new library like libglib-2.0.so.0.5000.0
# will take precedence over a stale library like
# libglib-2.0.so.0.4200.0 in the same directory without us needing
# to do anything, so the safe route is to avoid doing anything.
debug "Merged-/usr system, no need to do anything without --force"
return 0
fi
for soname in "$@"; do
do_soname "$multiarch" "$soname"
done
if [ -n "$need_ldconfig" ] && [ -n "$really" ]; then
warning "Changes were made, running ldconfig..."
ldconfig || ldconfig --verbose
elif [ -n "$need_ldconfig" ]; then
debug "Would run ldconfig, but skipped due to --dry-run"
fi
}
main "$@"
# vim:set sw=4 sts=4 et:

208
debian/control vendored
View file

@ -1,208 +0,0 @@
# This file is autogenerated. DO NOT EDIT!
#
# Modifications should be made to debian/control.in instead.
# This file is regenerated automatically in the clean target.
Source: glib2.0
Section: libs
Priority: optional
Maintainer: Ubuntu Developers <ubuntu-devel-discuss@lists.ubuntu.com>
XSBC-Original-Maintainer: Debian GNOME Maintainers <pkg-gnome-maintainers@lists.alioth.debian.org>
Uploaders: Iain Lane <laney@debian.org>, Jeremy Bicha <jbicha@ubuntu.com>, Simon McVittie <smcv@debian.org>
Build-Depends: dbus <!nocheck> <!noinsttest>,
debhelper-compat (= 13),
dh-sequence-python3,
dh-sequence-gnome,
docbook-xml,
docbook-xsl,
dpkg-dev (>= 1.17.14),
gettext,
libdbus-1-dev (>= 1.2.14) <!nocheck> <!noinsttest>,
libelf-dev (>= 0.142),
libffi-dev (>= 3.3),
libgamin-dev [hurd-any] | libfam-dev [hurd-any],
libmount-dev (>= 2.35.2-7~) [linux-any],
libpcre3-dev (>= 1:8.35),
libselinux1-dev [linux-any],
libxml2-utils,
linux-libc-dev [linux-any],
meson (>= 0.52.0),
pkg-config (>= 0.16.0),
python3-distutils,
python3:any (>= 2.7.5-5~),
xsltproc,
zlib1g-dev
Build-Depends-Arch: desktop-file-utils <!nocheck>,
locales <!nocheck> | locales-all <!nocheck>,
python3-dbus <!nocheck>,
python3-gi <!nocheck>,
shared-mime-info <!nocheck>,
tzdata <!nocheck>,
xterm <!nocheck>
Build-Depends-Indep: gtk-doc-tools (>= 1.32.1),
Rules-Requires-Root: no
Standards-Version: 4.6.0
Homepage: https://wiki.gnome.org/Projects/GLib
XS-Debian-Vcs-Browser: https://salsa.debian.org/gnome-team/glib
XS-Debian-Vcs-Git: https://salsa.debian.org/gnome-team/glib.git
Vcs-Browser: https://salsa.debian.org/gnome-team/glib/tree/ubuntu/jammy
Vcs-Git: https://salsa.debian.org/gnome-team/glib.git -b ubuntu/jammy
Package: libglib2.0-0
Architecture: any
Depends: ${misc:Depends},
${shlibs:Depends}
Recommends: libglib2.0-data,
shared-mime-info,
xdg-user-dirs
Breaks: gimp (<< 2.10.14-3~),
glib-networking-tests (<< 2.70.0~),
gnome-keyring (<< 40.0-3~),
libgio-fam (<< 2.64.1-2~) [kfreebsd-any hurd-any],
libgirepository-1.0-1 (<< 1.62.0-4~),
libgladeui-2-6 (<< 3.22.2),
libsoup2.4-tests (<< 2.72.0-3~),
Replaces: libgio-fam (<< 2.64.1-2~) [kfreebsd-any hurd-any]
Multi-Arch: same
Pre-Depends: ${misc:Pre-Depends}
Description: GLib library of C routines
GLib is a library containing many useful C routines for things such
as trees, hashes, lists, and strings. It is a useful general-purpose
C library used by projects such as GTK+, GIMP, and GNOME.
.
This package contains the shared libraries.
Package: libglib2.0-tests
Build-profiles: <!noinsttest>
Architecture: any
Depends: gir1.2-glib-2.0,
libglib2.0-dev-bin,
python3-dbus,
python3-dbusmock,
python3-gi,
shared-mime-info,
${misc:Depends},
${python3:Depends},
${shlibs:Depends}
Recommends: xdg-desktop-portal,
Pre-Depends: ${misc:Pre-Depends}
Description: GLib library of C routines - installed tests
GLib is a library containing many useful C routines for things such
as trees, hashes, lists, and strings. It is a useful general-purpose
C library used by projects such as GTK+, GIMP, and GNOME.
.
This package contains test programs, designed to be run as part of a
regression testsuite.
Package: libglib2.0-udeb
Build-Profiles: <!noudeb>
Section: debian-installer
Package-Type: udeb
Architecture: any
Depends: ${misc:Depends},
${shlibs:Depends}
Description: GLib library of C routines - minimal runtime
This is a udeb, or a microdeb, for the debian-installer.
.
GLib is a library containing many useful C routines for things such
as trees, hashes, lists, and strings. It is a useful general-purpose
C library used by projects such as GTK+, GIMP, and GNOME.
.
This package contains the minimal runtime library needed by the Debian
installer.
Package: libglib2.0-bin
Section: misc
Architecture: any
Pre-Depends: ${misc:Pre-Depends}
Depends: libglib2.0-data,
${misc:Depends},
${shlibs:Depends}
Multi-Arch: foreign
Description: Programs for the GLib library
GLib is a library containing many useful C routines for things such
as trees, hashes, lists, and strings. It is a useful general-purpose
C library used by projects such as GTK+, GIMP, and GNOME.
.
This package contains the program files which is used for the libraries
and others.
Package: libglib2.0-dev
Section: libdevel
Architecture: any
Multi-Arch: same
Depends: libffi-dev (>= 3.3),
libglib2.0-0 (= ${binary:Version}),
libglib2.0-bin (= ${binary:Version}),
libglib2.0-dev-bin (= ${binary:Version}),
libmount-dev (>= 2.35.2-7~) [linux-any],
libpcre3-dev (>= 1:8.31),
libselinux1-dev [linux-any],
pkg-config,
zlib1g-dev,
${misc:Depends},
${python3:Depends},
${shlibs:Depends}
Breaks: libglib2.0-0-dbg (<< 2.51.4-1~)
Replaces: libglib2.0-0-dbg (<< 2.51.4-1~)
Suggests: libgirepository1.0-dev (>= 1.62),
libglib2.0-doc
Description: Development files for the GLib library
GLib is a library containing many useful C routines for things such
as trees, hashes, lists, and strings. It is a useful general-purpose
C library used by projects such as GTK+, GIMP, and GNOME.
.
This package is needed to compile programs against libglib2.0-0,
as only it includes the header files and static libraries (optionally)
needed for compiling.
.
GObject-Introspection metadata for this library can be found in the
libgirepository1.0-dev package.
Package: libglib2.0-dev-bin
Section: libdevel
Architecture: any
Depends: python3-distutils,
${misc:Depends},
${python3:Depends},
${shlibs:Depends}
Suggests: libgdk-pixbuf2.0-bin (>= 2.36.12-2~) | libgdk-pixbuf2.0-dev,
libxml2-utils
Breaks: libglib2.0-bin (<< 2.54.2-5~),
libglib2.0-dev (<< 2.53)
Replaces: libglib2.0-bin (<< 2.54.2-5~),
libglib2.0-dev (<< 2.53)
Multi-Arch: foreign
Description: Development utilities for the GLib library
GLib is a library containing many useful C routines for things such
as trees, hashes, lists, and strings. It is a useful general-purpose
C library used by projects such as GTK+, GIMP, and GNOME.
.
This package is needed to compile programs against libglib2.0-0. It contains
development utilities typically run during compilation and should not be
installed directly. Use libglib2.0-dev instead.
Package: libglib2.0-data
Architecture: all
Depends: ${misc:Depends}
Multi-Arch: foreign
Description: Common files for GLib library
GLib is a library containing many useful C routines for things such
as trees, hashes, lists, and strings. It is a useful general-purpose
C library used by projects such as GTK+, GIMP, and GNOME.
.
This package is needed for the runtime libraries to display messages in
languages other than English.
Package: libglib2.0-doc
Section: doc
Architecture: all
Depends: ${misc:Depends}
Suggests: devhelp
Multi-Arch: foreign
Description: Documentation files for the GLib library
GLib is a library containing many useful C routines for things such
as trees, hashes, lists, and strings. It is a useful general-purpose
C library used by projects such as GTK+, GIMP, and GNOME.
.
This package contains the HTML documentation for the GLib library
in /usr/share/doc/libglib2.0-doc/ .

204
debian/control.in vendored
View file

@ -1,204 +0,0 @@
Source: glib2.0
Section: libs
Priority: optional
Maintainer: Ubuntu Developers <ubuntu-devel-discuss@lists.ubuntu.com>
XSBC-Original-Maintainer: Debian GNOME Maintainers <pkg-gnome-maintainers@lists.alioth.debian.org>
Uploaders: @GNOME_TEAM@, Simon McVittie <smcv@debian.org>
Build-Depends: dbus <!nocheck> <!noinsttest>,
debhelper-compat (= 13),
dh-sequence-python3,
dh-sequence-gnome,
docbook-xml,
docbook-xsl,
dpkg-dev (>= 1.17.14),
gettext,
libdbus-1-dev (>= 1.2.14) <!nocheck> <!noinsttest>,
libelf-dev (>= 0.142),
libffi-dev (>= 3.3),
libgamin-dev [hurd-any] | libfam-dev [hurd-any],
libmount-dev (>= 2.35.2-7~) [linux-any],
libpcre3-dev (>= 1:8.35),
libselinux1-dev [linux-any],
libxml2-utils,
linux-libc-dev [linux-any],
meson (>= 0.52.0),
pkg-config (>= 0.16.0),
python3-distutils,
python3:any (>= 2.7.5-5~),
xsltproc,
zlib1g-dev
Build-Depends-Arch: desktop-file-utils <!nocheck>,
locales <!nocheck> | locales-all <!nocheck>,
python3-dbus <!nocheck>,
python3-gi <!nocheck>,
shared-mime-info <!nocheck>,
tzdata <!nocheck>,
xterm <!nocheck>
Build-Depends-Indep: gtk-doc-tools (>= 1.32.1),
Rules-Requires-Root: no
Standards-Version: 4.6.0
Homepage: https://wiki.gnome.org/Projects/GLib
XS-Debian-Vcs-Browser: https://salsa.debian.org/gnome-team/glib
XS-Debian-Vcs-Git: https://salsa.debian.org/gnome-team/glib.git
Vcs-Browser: https://salsa.debian.org/gnome-team/glib/tree/ubuntu/jammy
Vcs-Git: https://salsa.debian.org/gnome-team/glib.git -b ubuntu/jammy
Package: libglib2.0-0
Architecture: any
Depends: ${misc:Depends},
${shlibs:Depends}
Recommends: libglib2.0-data,
shared-mime-info,
xdg-user-dirs
Breaks: gimp (<< 2.10.14-3~),
glib-networking-tests (<< 2.70.0~),
gnome-keyring (<< 40.0-3~),
libgio-fam (<< 2.64.1-2~) [kfreebsd-any hurd-any],
libgirepository-1.0-1 (<< 1.62.0-4~),
libgladeui-2-6 (<< 3.22.2),
libsoup2.4-tests (<< 2.72.0-3~),
Replaces: libgio-fam (<< 2.64.1-2~) [kfreebsd-any hurd-any]
Multi-Arch: same
Pre-Depends: ${misc:Pre-Depends}
Description: GLib library of C routines
GLib is a library containing many useful C routines for things such
as trees, hashes, lists, and strings. It is a useful general-purpose
C library used by projects such as GTK+, GIMP, and GNOME.
.
This package contains the shared libraries.
Package: libglib2.0-tests
Build-profiles: <!noinsttest>
Architecture: any
Depends: gir1.2-glib-2.0,
libglib2.0-dev-bin,
python3-dbus,
python3-dbusmock,
python3-gi,
shared-mime-info,
${misc:Depends},
${python3:Depends},
${shlibs:Depends}
Recommends: xdg-desktop-portal,
Pre-Depends: ${misc:Pre-Depends}
Description: GLib library of C routines - installed tests
GLib is a library containing many useful C routines for things such
as trees, hashes, lists, and strings. It is a useful general-purpose
C library used by projects such as GTK+, GIMP, and GNOME.
.
This package contains test programs, designed to be run as part of a
regression testsuite.
Package: libglib2.0-udeb
Build-Profiles: <!noudeb>
Section: debian-installer
Package-Type: udeb
Architecture: any
Depends: ${misc:Depends},
${shlibs:Depends}
Description: GLib library of C routines - minimal runtime
This is a udeb, or a microdeb, for the debian-installer.
.
GLib is a library containing many useful C routines for things such
as trees, hashes, lists, and strings. It is a useful general-purpose
C library used by projects such as GTK+, GIMP, and GNOME.
.
This package contains the minimal runtime library needed by the Debian
installer.
Package: libglib2.0-bin
Section: misc
Architecture: any
Pre-Depends: ${misc:Pre-Depends}
Depends: libglib2.0-data,
${misc:Depends},
${shlibs:Depends}
Multi-Arch: foreign
Description: Programs for the GLib library
GLib is a library containing many useful C routines for things such
as trees, hashes, lists, and strings. It is a useful general-purpose
C library used by projects such as GTK+, GIMP, and GNOME.
.
This package contains the program files which is used for the libraries
and others.
Package: libglib2.0-dev
Section: libdevel
Architecture: any
Multi-Arch: same
Depends: libffi-dev (>= 3.3),
libglib2.0-0 (= ${binary:Version}),
libglib2.0-bin (= ${binary:Version}),
libglib2.0-dev-bin (= ${binary:Version}),
libmount-dev (>= 2.35.2-7~) [linux-any],
libpcre3-dev (>= 1:8.31),
libselinux1-dev [linux-any],
pkg-config,
zlib1g-dev,
${misc:Depends},
${python3:Depends},
${shlibs:Depends}
Breaks: libglib2.0-0-dbg (<< 2.51.4-1~)
Replaces: libglib2.0-0-dbg (<< 2.51.4-1~)
Suggests: libgirepository1.0-dev (>= 1.62),
libglib2.0-doc
Description: Development files for the GLib library
GLib is a library containing many useful C routines for things such
as trees, hashes, lists, and strings. It is a useful general-purpose
C library used by projects such as GTK+, GIMP, and GNOME.
.
This package is needed to compile programs against libglib2.0-0,
as only it includes the header files and static libraries (optionally)
needed for compiling.
.
GObject-Introspection metadata for this library can be found in the
libgirepository1.0-dev package.
Package: libglib2.0-dev-bin
Section: libdevel
Architecture: any
Depends: python3-distutils,
${misc:Depends},
${python3:Depends},
${shlibs:Depends}
Suggests: libgdk-pixbuf2.0-bin (>= 2.36.12-2~) | libgdk-pixbuf2.0-dev,
libxml2-utils
Breaks: libglib2.0-bin (<< 2.54.2-5~),
libglib2.0-dev (<< 2.53)
Replaces: libglib2.0-bin (<< 2.54.2-5~),
libglib2.0-dev (<< 2.53)
Multi-Arch: foreign
Description: Development utilities for the GLib library
GLib is a library containing many useful C routines for things such
as trees, hashes, lists, and strings. It is a useful general-purpose
C library used by projects such as GTK+, GIMP, and GNOME.
.
This package is needed to compile programs against libglib2.0-0. It contains
development utilities typically run during compilation and should not be
installed directly. Use libglib2.0-dev instead.
Package: libglib2.0-data
Architecture: all
Depends: ${misc:Depends}
Multi-Arch: foreign
Description: Common files for GLib library
GLib is a library containing many useful C routines for things such
as trees, hashes, lists, and strings. It is a useful general-purpose
C library used by projects such as GTK+, GIMP, and GNOME.
.
This package is needed for the runtime libraries to display messages in
languages other than English.
Package: libglib2.0-doc
Section: doc
Architecture: all
Depends: ${misc:Depends}
Suggests: devhelp
Multi-Arch: foreign
Description: Documentation files for the GLib library
GLib is a library containing many useful C routines for things such
as trees, hashes, lists, and strings. It is a useful general-purpose
C library used by projects such as GTK+, GIMP, and GNOME.
.
This package contains the HTML documentation for the GLib library
in /usr/share/doc/libglib2.0-doc/ .

107
debian/copyright vendored
View file

@ -1,107 +0,0 @@
This package was debianized by Akira TAGOH <tagoh@debian.org> on
Thu, 7 Mar 2002 01:05:25 +0900.
It was downloaded from <https://download.gnome.org/sources/glib/>.
Original Authors
----------------
Peter Mattis <petm@xcf.berkeley.edu>
Spencer Kimball <spencer@xcf.berkeley.edu>
Josh MacDonald <jmacd@xcf.berkeley.edu>
Please do not mail the original authors asking questions about this
version of GLib.
GLib Team
---------
Shawn T. Amundson <amundson@gimp.org>
Jeff Garzik <jgarzik@pobox.com>
Raja R Harinath <harinath@cs.umn.edu>
Tim Janik <timj@gtk.org>
Elliot Lee <sopwith@redhat.com>
Tor Lillqvist <tml@iki.fi>
Paolo Molaro <lupus@debian.org>
Havoc Pennington <hp@pobox.com>
Manish Singh <yosh@gimp.org>
Owen Taylor <otaylor@gtk.org>
Sebastian Wilhelmi <wilhelmi@ira.uka.de>
The random number generator "Mersenne Twister", which is used by GLib,
was developed and originally coded by:
Makoto Matsumoto <matumoto@math.keio.ac.jp>
Takuji Nishimura <nisimura@math.keio.ac.jp>
Major copyright holders:
Copyright © 1995-2021 Red Hat, Inc.
Copyright © 2008-2010 Novell, Inc.
Copyright © 2008-2010 Codethink Limited.
Copyright © 2008-2018 Collabora, Ltd.
Copyright © 2018 Endless Mobile, Inc.
Copyright © 2018 Emmanuele Bassi
License:
This package is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This package is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this package; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
On Debian systems, the complete text of the GNU Lesser General
Public License can be found in `/usr/share/common-licenses/LGPL'.
Files:
gobject/tests/taptestrunner.py
Copyright:
2015 Remko Tronçon
License: Expat
Files:
tests/gen-casefold-txt.py
tests/gen-casemap-txt.py
Copyright:
1998-1999 Tom Tromey
2001 Red Hat Software
License: GPL-2+
License: Expat
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
.
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
License: GPL-2+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
.
You should have received a copy of the GNU General Public License
along with this program; if not, see <http://www.gnu.org/licenses/>.

2
debian/docs vendored
View file

@ -1,2 +0,0 @@
NEWS
README.md

18
debian/gbp.conf vendored
View file

@ -1,18 +0,0 @@
[DEFAULT]
pristine-tar = True
debian-branch = ubuntu/jammy
debian-tag = ubuntu/%(version)s
upstream-branch = upstream/2.72.x
[buildpackage]
sign-tags = True
[dch]
multimaint-merge = True
[import-orig]
postimport = dch -v%(version)s New upstream release; git add debian/changelog; debcommit
upstream-vcs-tag = %(version%~%.)s
[pq]
patch-numbers = False

View file

@ -1,12 +0,0 @@
#!/bin/sh
# Fallback implementation of gio-launch-desktop. If we upgrade from a
# GLib version between 2.57.2 and 2.63.5, as long as that version is
# still loaded into some process, it requires this executable to launch
# .desktop files.
#
# This script will be removed after Ubuntu 20.04 and Debian 11 are released.
# Do not rely on it.
set -eu
export GIO_LAUNCHED_DESKTOP_FILE_PID="$$"
exec "$@"

View file

@ -1,2 +0,0 @@
/usr/lib/${DEB_HOST_MULTIARCH}/gio/modules
/usr/share/glib-2.0/schemas

View file

@ -1,7 +0,0 @@
usr/lib/*/libglib*.so.*
usr/lib/*/libgobject*.so.*
usr/lib/*/libgmodule*.so.*
usr/lib/*/libgthread*.so.*
usr/lib/*/libgio*.so.*
usr/bin/gio-querymodules usr/lib/${DEB_HOST_MULTIARCH}/glib-2.0
usr/bin/glib-compile-schemas usr/lib/${DEB_HOST_MULTIARCH}/glib-2.0

View file

@ -1,7 +0,0 @@
# GObject uses GLib functions instead of using libc directly
libglib2.0-0: hardening-no-fortify-functions [usr/lib/*/libgobject-2.0.so.*]
# It's a deliberate choice of bundling them together
libglib2.0-0: package-name-doesnt-match-sonames libgio-2.0-0 libglib-2.0-0 libgmodule-2.0-0 libgobject-2.0-0 libgthread-2.0-0
# These empty directories are deliberate.
libglib2.0-0: package-contains-empty-directory usr/lib/*/gio/modules/
libglib2.0-0: package-contains-empty-directory usr/share/glib-2.0/schemas/

View file

@ -1,68 +0,0 @@
#!/bin/sh
set -e
handle_triggers () {
local trigger
local dirs
for trigger in "$@"; do
if ! [ -d $trigger ]; then
continue
fi
case $trigger in
/usr/share/glib-2.0/schemas)
# This is triggered everytime an application installs a
# GSettings schema
"/usr/lib/#MULTIARCH#/glib-2.0/glib-compile-schemas" /usr/share/glib-2.0/schemas || true
;;
"/usr/lib/#MULTIARCH#/gio/modules")
# This is triggered everytime an application installs a GIO
# module into /usr/lib/#MULTIARCH#/gio/modules
"/usr/lib/#MULTIARCH#/glib-2.0/gio-querymodules" "/usr/lib/#MULTIARCH#/gio/modules" || true
;;
esac
done
}
cleanup () {
/usr/share/glib-2.0/clean-up-unmanaged-libraries \
--bug-ref=896019 \
"$@" \
"#MULTIARCH#" \
libglib-2.0.so.0
}
if [ "$1" = triggered ]; then
handle_triggers $2
exit 0
fi
# Clean up stale shared libraries on upgrades if necessary. Do this before running
# glib-compile-schemas, gio-querymodules.
# This workaround can be removed after Ubuntu 22.04 is released.
if [ -n "$2" ] && ! cleanup; then
echo "$0: Trying cleanup again with more logging..."
cleanup --verbose
fi
#DEBHELPER#
# This is shipped in the .deb (see debian/libglib2.0-0.dirs) but would
# be removed if empty during upgrade by old versions of the postrm (#987913).
# This workaround can be removed after Ubuntu 22.04 is released.
install -d "/usr/lib/#MULTIARCH#/gio/modules"
"/usr/lib/#MULTIARCH#/glib-2.0/glib-compile-schemas" /usr/share/glib-2.0/schemas || true
"/usr/lib/#MULTIARCH#/glib-2.0/gio-querymodules" "/usr/lib/#MULTIARCH#/gio/modules" || true
# Clean up pre-multiarch giomodule.cache.
# This workaround can be removed after Debian 12 and Ubuntu 22.04 are released.
if [ -d /usr/lib/gio/modules ]; then
rm -f /usr/lib/gio/modules/giomodule.cache
rmdir -p --ignore-fail-on-non-empty /usr/lib/gio/modules
fi
# vim:set sw=4 sts=4 et:

View file

@ -1,21 +0,0 @@
#! /bin/sh
set -e
#DEBHELPER#
case "$1" in
(remove|purge)
if [ -d /usr/lib/#MULTIARCH#/gio/modules ]; then
# Purge the cache
rm -f /usr/lib/#MULTIARCH#/gio/modules/giomodule.cache
rmdir -p --ignore-fail-on-non-empty /usr/lib/#MULTIARCH#/gio/modules
fi
;;
esac
if [ "$1" = purge ] && [ -d /usr/share/glib-2.0/schemas ] && [ "$DPKG_MAINTSCRIPT_PACKAGE_REFCOUNT" = 1 ]; then
# This is the last multiarch variant to be removed, so drop the
# architecture-independent compiled schemas
rm -f /usr/share/glib-2.0/schemas/gschemas.compiled
rmdir -p --ignore-fail-on-non-empty /usr/share/glib-2.0/schemas
fi

File diff suppressed because it is too large Load diff

View file

@ -1,2 +0,0 @@
interest-noawait /usr/lib/#MULTIARCH#/gio/modules
interest-await /usr/share/glib-2.0/schemas

View file

@ -1,13 +0,0 @@
usr/bin/gapplication
usr/bin/gdbus
usr/bin/gio
usr/bin/gresource
usr/bin/gsettings
usr/share/bash-completion
usr/share/man/man1/gapplication.1*
usr/share/man/man1/gdbus.1*
usr/share/man/man1/gio-querymodules.1*
usr/share/man/man1/gio.1*
usr/share/man/man1/glib-compile-schemas.1*
usr/share/man/man1/gresource.1*
usr/share/man/man1/gsettings.1*

View file

@ -1,2 +0,0 @@
/usr/lib/${DEB_HOST_MULTIARCH}/glib-2.0/gio-querymodules /usr/bin/gio-querymodules
/usr/lib/${DEB_HOST_MULTIARCH}/glib-2.0/glib-compile-schemas /usr/bin/glib-compile-schemas

View file

@ -1,2 +0,0 @@
# GLib programs normally use GLib functions instead of using libc directly
libglib2.0-bin: hardening-no-fortify-functions [usr/bin/gio]

View file

@ -1 +0,0 @@
usr/share/locale

View file

@ -1,19 +0,0 @@
usr/bin/gdbus-codegen
usr/bin/glib-compile-resources
usr/bin/glib-genmarshal
usr/bin/glib-gettextize
usr/bin/glib-mkenums
usr/bin/gobject-query
usr/bin/gtester
usr/bin/gtester-report
usr/share/aclocal
usr/share/glib-2.0/codegen/*.py
usr/share/glib-2.0/gettext
usr/share/man/man1/gdbus-codegen.1*
usr/share/man/man1/glib-compile-resources.1*
usr/share/man/man1/glib-genmarshal.1*
usr/share/man/man1/glib-gettextize.1*
usr/share/man/man1/glib-mkenums.1*
usr/share/man/man1/gobject-query.1*
usr/share/man/man1/gtester-report.1*
usr/share/man/man1/gtester.1*

View file

@ -1,15 +0,0 @@
GLib2.0 for Debian
-------------------
Static libraries issue:
Right now glib2.0 provides some static libraries. If your application
uses g_module* functions or other libraries uses g_module* functions and
your application link it, Please don't statically link this libraries.
You may get some strange proglem between static-linked application and
dynamic-loaded modules, g_module* provides the feature for dynamically
loading some modules.
This is well-known bug, so please don't file a bug report.
-- Akira TAGOH <tagoh@debian.org>, Thu, 11 Apr 2002 19:28:50 +0900

View file

@ -1,14 +0,0 @@
usr/include/*
usr/lib/*/glib-2.0
usr/lib/*/lib*.a
usr/lib/*/libgio*.so
usr/lib/*/libglib*.so
usr/lib/*/libgmodule*.so
usr/lib/*/libgobject*.so
usr/lib/*/libgthread*.so
usr/lib/*/pkgconfig
usr/share/gdb
usr/share/gettext/its
usr/share/glib-2.0/gdb
usr/share/glib-2.0/schemas
usr/share/glib-2.0/valgrind

View file

@ -1,14 +0,0 @@
Document: gio
Title: GIO (GLib) Reference Manual
Author: Damon Chaplin et al.
Abstract: GIO is striving to provide a modern, easy-to-use VFS API that sits at
the right level in the library stack. The goal is to overcome the shortcomings
of GnomeVFS and provide an API that is so good that developers prefer it over
raw POSIX calls. Among other things that means using GObject. It also means
not cloning the POSIX API, but providing higher-level, document-centric
interfaces.
Section: Programming/C
Format: HTML
Index: /usr/share/doc/libglib2.0-doc/gio/index.html
Files: /usr/share/doc/libglib2.0-doc/gio/*.html

View file

@ -1,12 +0,0 @@
Document: glib
Title: GLib Reference Manual
Author: Damon Chaplin et al.
Abstract: The GLib C library is used in GTK+ and GNOME
programs as a general-purpose set of functions for hash, tree, list,
and string operations, which C is oddly lacking whatsoever in any
of its standard libraries.
Section: Programming/C
Format: HTML
Index: /usr/share/doc/libglib2.0-doc/glib/index.html
Files: /usr/share/doc/libglib2.0-doc/glib/*.html

View file

@ -1,15 +0,0 @@
Document: gobject
Title: GObject (GLib) Reference Manual
Author: Damon Chaplin et al.
Abstract: Most modern programming languages come with their own native object
systems and additional fundamental algorithmic language constructs.
Just as GLib serves as an implementation of such fundamental
types and algorithms (linked lists, hash tables and so forth), the
GLib Object System provides the required implementations of a
flexible extensible and intentionally easy to map (into other
languages) object oriented framework for C.
Section: Programming/C
Format: HTML
Index: /usr/share/doc/libglib2.0-doc/gobject/index.html
Files: /usr/share/doc/libglib2.0-doc/gobject/*.html

View file

@ -1,3 +0,0 @@
usr/share/gtk-doc/html/gio
usr/share/gtk-doc/html/glib
usr/share/gtk-doc/html/gobject

View file

@ -1,3 +0,0 @@
usr/share/gtk-doc/html/gio usr/share/doc/libglib2.0-doc/gio
usr/share/gtk-doc/html/glib usr/share/doc/libglib2.0-doc/glib
usr/share/gtk-doc/html/gobject usr/share/doc/libglib2.0-doc/gobject

View file

@ -1,2 +0,0 @@
# https://bugs.debian.org/970275
package-contains-documentation-outside-usr-share-doc usr/share/gtk-doc/html/*

View file

@ -1,6 +0,0 @@
dir_to_symlink /usr/share/doc/libglib2.0-doc/gio ../../gtk-doc/html/gio 2.58.0-4~
dir_to_symlink /usr/share/doc/libglib2.0-doc/glib ../../gtk-doc/html/glib 2.58.0-4~
dir_to_symlink /usr/share/doc/libglib2.0-doc/gobject ../../gtk-doc/html/gobject 2.58.0-4~
symlink_to_dir /usr/share/gtk-doc/html/gio ../../doc/libglib2.0-doc/gio 2.58.0-4~
symlink_to_dir /usr/share/gtk-doc/html/glib ../../doc/libglib2.0-doc/glib 2.58.0-4~
symlink_to_dir /usr/share/gtk-doc/html/gobject ../../doc/libglib2.0-doc/gobject 2.58.0-4~

View file

@ -1,2 +0,0 @@
usr/libexec/installed-tests
usr/share/installed-tests

View file

@ -1,12 +0,0 @@
# Lots of tests don't use libc functions
libglib2.0-tests: hardening-no-fortify-functions [usr/libexec/installed-tests/glib/*]
# Some are deliberately not well-formed UTF-8
libglib2.0-tests: national-encoding usr/libexec/installed-tests/glib/markups/fail*
# Not every .txt file is documentation
libglib2.0-tests: package-contains-documentation-outside-usr-share-doc usr/libexec/installed-tests/glib/*.txt
# Test data for content-type sniffing, never actually executed
libglib2.0-tests: script-not-executable [usr/libexec/installed-tests/glib/x-content/unix-software/autorun.sh]
# This is lorem ipsum in a test-case, nothing to do with the Debian Free Software Guidelines
libglib2.0-tests: spelling-error-in-binary usr/libexec/installed-tests/glib/utf8-pointer dsfg dfsg
# Depends on a private test-only library
libglib2.0-tests: custom-library-search-path RUNPATH /usr/libexec/installed-tests/glib [usr/libexec/installed-tests/glib/gdbus-peer]

View file

@ -1,2 +0,0 @@
usr/lib/*/lib*.so.*
usr/share/locale

View file

@ -1,2 +0,0 @@
# It's a deliberate choice of bundling them together
libglib2.0-udeb udeb: package-name-doesnt-match-sonames libgio-2.0-0 libglib-2.0-0 libgmodule-2.0-0 libgobject-2.0-0 libgthread-2.0-0

File diff suppressed because it is too large Load diff

View file

@ -1,38 +0,0 @@
From: Ryan Lortie <desrt@desrt.ca>
Date: Tue, 4 Mar 2014 09:20:38 -0500
Subject: timer test: use 'volatile' for locals
GCC seems to be failing to follow the letter of the C spec by allowing extra
precision in floating point values to persist across assignments which are
optimised away.
Force its hand by using 'volatile' on the locals in question.
Bug: https://gitlab.gnome.org/GNOME/glib/issues/820
Forwarded: yes
---
glib/tests/timer.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/glib/tests/timer.c b/glib/tests/timer.c
index 102406e..8ea5c1f 100644
--- a/glib/tests/timer.c
+++ b/glib/tests/timer.c
@@ -30,7 +30,7 @@ static void
test_timer_basic (void)
{
GTimer *timer;
- gdouble elapsed;
+ volatile gdouble elapsed;
gulong micros;
timer = g_timer_new ();
@@ -65,7 +65,7 @@ static void
test_timer_stop (void)
{
GTimer *timer;
- gdouble elapsed, elapsed2;
+ volatile gdouble elapsed, elapsed2;
timer = g_timer_new ();

View file

@ -1,167 +0,0 @@
From: Philip Withnall <withnall@endlessm.com>
Date: Thu, 23 Nov 2017 18:48:58 +0000
Subject: Call gettext if .desktop file does not have inline translations
Patch from OpenSUSE via Ubuntu, original author unknown. Martin Pitt and
Vincent Untz appear to be the main authors.
Reworked slightly by Philip Withnall to avoid exposing new public API
for the non-standard keys.
Bug: https://bugzilla.gnome.org/show_bug.cgi?id=569829
Bug-Ubuntu: https://launchpad.net/bugs/3935
Applied-upstream: no, rejected because "this will be solved soon" (in 2013)
---
glib/gkeyfile.c | 83 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 83 insertions(+)
diff --git a/glib/gkeyfile.c b/glib/gkeyfile.c
index 6460970..762dfef 100644
--- a/glib/gkeyfile.c
+++ b/glib/gkeyfile.c
@@ -489,6 +489,17 @@
* Since: 2.14
*/
+/* Downstream Debian defines for calling gettext() if a .desktop file doesnt
+ * contain translations. These are not standardised.
+ *
+ * See: https://launchpad.net/bugs/3935
+ * See:http://bugzilla.gnome.org/show_bug.cgi?id=569829
+ */
+#define G_KEY_FILE_DESKTOP_ACTION_GROUP_PREFIX "Desktop Action"
+#define G_KEY_FILE_DESKTOP_KEY_GETTEXT_DOMAIN "X-GNOME-Gettext-Domain"
+#define G_KEY_FILE_DESKTOP_KEY_FULLNAME "X-GNOME-FullName"
+#define G_KEY_FILE_DESKTOP_KEY_KEYWORDS "Keywords"
+
typedef struct _GKeyFileGroup GKeyFileGroup;
/**
@@ -513,6 +524,7 @@ struct _GKeyFile
gboolean checked_locales; /* TRUE if @locales has been initialised */
gchar **locales; /* (nullable) */
+ gchar *gettext_domain;
gint ref_count; /* (atomic) */
};
@@ -639,6 +651,7 @@ g_key_file_init (GKeyFile *key_file)
key_file->parse_buffer = NULL;
key_file->list_separator = ';';
key_file->flags = 0;
+ key_file->gettext_domain = NULL;
}
static void
@@ -659,6 +672,12 @@ g_key_file_clear (GKeyFile *key_file)
key_file->parse_buffer = NULL;
}
+ if (key_file->gettext_domain)
+ {
+ g_free (key_file->gettext_domain);
+ key_file->gettext_domain = NULL;
+ }
+
tmp = key_file->groups;
while (tmp != NULL)
{
@@ -879,6 +898,11 @@ g_key_file_load_from_fd (GKeyFile *key_file,
return FALSE;
}
+ key_file->gettext_domain = g_key_file_get_string (key_file,
+ G_KEY_FILE_DESKTOP_GROUP,
+ G_KEY_FILE_DESKTOP_KEY_GETTEXT_DOMAIN,
+ NULL);
+
return TRUE;
}
@@ -991,6 +1015,11 @@ g_key_file_load_from_data (GKeyFile *key_file,
return FALSE;
}
+ key_file->gettext_domain = g_key_file_get_string (key_file,
+ G_KEY_FILE_DESKTOP_GROUP,
+ G_KEY_FILE_DESKTOP_KEY_GETTEXT_DOMAIN,
+ NULL);
+
return TRUE;
}
@@ -2240,6 +2269,8 @@ g_key_file_get_locale_string (GKeyFile *key_file,
GError *key_file_error;
gchar **languages;
gboolean free_languages = FALSE;
+ gboolean try_gettext = FALSE;
+ const gchar *msg_locale;
gint i;
g_return_val_if_fail (key_file != NULL, NULL);
@@ -2261,6 +2292,25 @@ g_key_file_get_locale_string (GKeyFile *key_file,
free_languages = FALSE;
}
+ /* we're only interested in gettext translation if we don't have a
+ * translation in the .desktop file itself and if the key is one of the keys
+ * we know we want to translate: Name, GenericName, Comment, Keywords.
+ * Blindly doing this for all keys can give strange result for the icons,
+ * since the Icon is a locale string in the spec, eg. We also only get
+ * translation in the mo file if the requested locale is the LC_MESSAGES one.
+ * Ideally, we should do more and change LC_MESSAGES to use the requested
+ * locale, but there's no guarantee it's installed on the system and it might
+ * have some side-effects. Since this is a corner case, let's ignore it. */
+ msg_locale = setlocale (LC_MESSAGES, NULL);
+ try_gettext = msg_locale && key_file->gettext_domain &&
+ (strcmp (group_name, G_KEY_FILE_DESKTOP_GROUP) == 0 ||
+ g_str_has_prefix (group_name, G_KEY_FILE_DESKTOP_ACTION_GROUP_PREFIX)) &&
+ (strcmp (key, G_KEY_FILE_DESKTOP_KEY_NAME) == 0 ||
+ strcmp (key, G_KEY_FILE_DESKTOP_KEY_FULLNAME) == 0 ||
+ strcmp (key, G_KEY_FILE_DESKTOP_KEY_GENERIC_NAME) == 0 ||
+ strcmp (key, G_KEY_FILE_DESKTOP_KEY_KEYWORDS) == 0 ||
+ strcmp (key, G_KEY_FILE_DESKTOP_KEY_COMMENT) == 0);
+
for (i = 0; languages[i]; i++)
{
candidate_key = g_strdup_printf ("%s[%s]", key, languages[i]);
@@ -2274,6 +2324,39 @@ g_key_file_get_locale_string (GKeyFile *key_file,
break;
}
+ /* Fallback to gettext */
+ if (try_gettext && !translated_value)
+ {
+ gchar *orig_value = g_key_file_get_string (key_file, group_name, key, NULL);
+
+ if (orig_value)
+ {
+ gboolean codeset_set;
+ const gchar *translated;
+ gboolean has_gettext;
+
+ codeset_set = bind_textdomain_codeset (key_file->gettext_domain, "UTF-8") != NULL;
+ translated = NULL;
+
+ translated = g_dgettext (key_file->gettext_domain,
+ orig_value);
+ has_gettext = translated != orig_value;
+
+ g_free (orig_value);
+
+ if (has_gettext)
+ {
+ if (codeset_set)
+ translated_value = g_strdup (translated);
+ else
+ translated_value = g_locale_to_utf8 (translated,
+ -1, NULL, NULL, NULL);
+ }
+ else
+ translated_value = NULL;
+ }
+ }
+
/* Fallback to untranslated key
*/
if (!translated_value)

View file

@ -1,51 +0,0 @@
From: Martin Pitt <mpitt@debian.org>
Date: Tue, 24 Feb 2009 16:08:05 +0100
Subject: Provide backwards compatibility for 01_gettext-desktopfiles.patch
for X-{Debian,Ubuntu}-Gettext-Domain
Ubuntu-specific. 01_gettext-desktopfiles.patch was changed to use
X-GNOME-, so this is necessary until all our .desktop files are converted.
Forwarded: no
---
glib/gkeyfile.c | 20 ++++++++++++++++++++
1 file changed, 20 insertions(+)
diff --git a/glib/gkeyfile.c b/glib/gkeyfile.c
index 762dfef..6b9f45b 100644
--- a/glib/gkeyfile.c
+++ b/glib/gkeyfile.c
@@ -902,6 +902,16 @@ g_key_file_load_from_fd (GKeyFile *key_file,
G_KEY_FILE_DESKTOP_GROUP,
G_KEY_FILE_DESKTOP_KEY_GETTEXT_DOMAIN,
NULL);
+ if (!key_file->gettext_domain)
+ key_file->gettext_domain = g_key_file_get_string (key_file,
+ G_KEY_FILE_DESKTOP_GROUP,
+ "X-Ubuntu-Gettext-Domain",
+ NULL);
+ if (!key_file->gettext_domain)
+ key_file->gettext_domain = g_key_file_get_string (key_file,
+ G_KEY_FILE_DESKTOP_GROUP,
+ "X-Debian-Gettext-Domain",
+ NULL);
return TRUE;
}
@@ -1019,6 +1029,16 @@ g_key_file_load_from_data (GKeyFile *key_file,
G_KEY_FILE_DESKTOP_GROUP,
G_KEY_FILE_DESKTOP_KEY_GETTEXT_DOMAIN,
NULL);
+ if (!key_file->gettext_domain)
+ key_file->gettext_domain = g_key_file_get_string (key_file,
+ G_KEY_FILE_DESKTOP_GROUP,
+ "X-Ubuntu-Gettext-Domain",
+ NULL);
+ if (!key_file->gettext_domain)
+ key_file->gettext_domain = g_key_file_get_string (key_file,
+ G_KEY_FILE_DESKTOP_GROUP,
+ "X-Debian-Gettext-Domain",
+ NULL);
return TRUE;
}

View file

@ -1,36 +0,0 @@
From: Iain Lane <iain.lane@canonical.com>
Date: Mon, 10 Sep 2012 16:25:18 +0100
Subject: Disable confusing (to users) warning about deprecated schema paths
Disable a warning when compiling schemas which are installed
into 'deprecated' locations. Users see this very often due to
glib-compile-schemas being called from libglib2.0-0's trigger and it is
not very useful for them.
Forwarded: not-needed
---
gio/glib-compile-schemas.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/gio/glib-compile-schemas.c b/gio/glib-compile-schemas.c
index 7e1152f..57f6b96 100644
--- a/gio/glib-compile-schemas.c
+++ b/gio/glib-compile-schemas.c
@@ -1232,6 +1232,9 @@ parse_state_start_schema (ParseState *state,
return;
}
+ // Disable this warning: it confuses users and there is unlikely to be much
+ // progress towards fixing
+ /*
if (path && (g_str_has_prefix (path, "/apps/") ||
g_str_has_prefix (path, "/desktop/") ||
g_str_has_prefix (path, "/system/")))
@@ -1244,6 +1247,7 @@ parse_state_start_schema (ParseState *state,
g_printerr ("%s\n", message);
g_free (message);
}
+ */
state->schema_state = schema_state_new (path, gettext_domain,
extends, extends_name, list_of);

View file

@ -1,33 +0,0 @@
From: Martin Pitt <martin.pitt@ubuntu.com>
Date: Tue, 26 Jun 2012 19:28:14 +0200
Subject: Do not fail the /thread/thread4 test if prlimit() fails
This happens on the Debian buildds.
[smcv: Use g_test_skip()]
Forwarded: no, Debian buildd specific
---
glib/tests/thread.c | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)
diff --git a/glib/tests/thread.c b/glib/tests/thread.c
index 2bae96c..d2a91bf 100644
--- a/glib/tests/thread.c
+++ b/glib/tests/thread.c
@@ -146,7 +146,14 @@ test_thread4 (void)
nl.rlim_cur = 1;
if ((ret = prlimit (getpid (), RLIMIT_NPROC, &nl, &ol)) != 0)
- g_error ("prlimit failed: %s", g_strerror (errno));
+ {
+ gchar *message = g_strdup_printf ("setting PRLIMIT_NPROC to {cur=%d,max=%d} failed: %s",
+ (int) nl.rlim_cur, (int) nl.rlim_max,
+ g_strerror (errno));
+ g_test_skip (message);
+ g_free (message);
+ return;
+ }
error = NULL;
thread = g_thread_try_new ("a", thread1_func, NULL, &error);

View file

@ -1,70 +0,0 @@
From: Simon McVittie <smcv@debian.org>
Date: Sun, 24 Oct 2021 22:40:11 +0100
Subject: Add extra debug to memory-monitor-dbus test
Hopefully this will give us the necessary information to find out why
this test isn't reliable.
Bug-Debian: https://bugs.debian.org/995178
Forwarded: no
---
gio/tests/memory-monitor-dbus.py.in | 18 ++++++++++++++++--
1 file changed, 16 insertions(+), 2 deletions(-)
diff --git a/gio/tests/memory-monitor-dbus.py.in b/gio/tests/memory-monitor-dbus.py.in
index 17862e3..61e6f94 100755
--- a/gio/tests/memory-monitor-dbus.py.in
+++ b/gio/tests/memory-monitor-dbus.py.in
@@ -74,18 +74,29 @@ try:
Timeout is in deciseconds, defaulting to 50 (5 seconds). message is
printed on failure.
'''
+ print('Waiting up to {}/10 seconds for {!r} to be true'.format(timeout, condition))
+ orig_timeout = timeout
+
while timeout >= 0:
+ print('Loop iteration')
context = GLib.MainContext.default()
while context.iteration(False):
+ print('Iterating main loop')
pass
if condition():
+ print('Condition reached')
break
timeout -= 1
time.sleep(0.1)
else:
+ print('Condition not reached in {}/10 seconds'.format(orig_timeout))
self.fail(message or 'timed out waiting for ' + str(condition))
def memory_warning_cb(self, monitor, level):
+ print('low-memory-warning: monitor {!r} reports level {}'.format(
+ monitor,
+ level,
+ ))
self.last_warning = level
self.main_context.wakeup()
@@ -95,17 +106,20 @@ try:
# Wait 2 seconds
timeout = 2
while timeout > 0:
+ print('Waiting 0.5s for stray events...')
time.sleep(0.5)
timeout -= 0.5
self.main_context.iteration(False)
+ print('Emitting mock low-memory warning, level 100: try to free memory')
self.dbusmock.EmitWarning(100)
# Wait 2 seconds or until warning
- self.assertEventually(lambda: self.last_warning == 100, "'100' low-memory warning not received", 20)
+ self.assertEventually(lambda: self.last_warning == 100, "'100' low-memory warning not received", 100)
+ print('Emitting mock low-memory warning, level 255: OOM imminent')
self.dbusmock.EmitWarning(255)
# Wait 2 seconds or until warning
- self.assertEventually(lambda: self.last_warning == 255, "'255' low-memory warning not received", 20)
+ self.assertEventually(lambda: self.last_warning == 255, "'255' low-memory warning not received", 100)
except ImportError as e:
@unittest.skip("Cannot import %s" % e.name)

View file

@ -1,70 +0,0 @@
From: Martin Pitt <martin.pitt@ubuntu.com>
Date: Thu, 27 Sep 2012 11:22:56 +0200
Subject: Disable some tests on slow architectures which keep failing the
tests
[smcv: Modified to use g_test_skip() instead of omitting those test cases
completely, and allow them to be re-enabled with a Debian-specific
environment variable]
Co-authored-by: Simon McVittie <smcv@debian.org>
Forwarded: no
---
glib/tests/mainloop.c | 16 ++++++++++++++++
glib/tests/timeout.c | 9 +++++++++
2 files changed, 25 insertions(+)
diff --git a/glib/tests/mainloop.c b/glib/tests/mainloop.c
index 2bbb3d8..d6220a6 100644
--- a/glib/tests/mainloop.c
+++ b/glib/tests/mainloop.c
@@ -520,6 +520,14 @@ test_child_sources (void)
GMainLoop *loop;
GSource *parent, *child_b, *child_c, *end;
+#if defined(__arm__)
+ if (g_getenv ("DEB_ALLOW_FLAKY_TESTS") == NULL)
+ {
+ g_test_skip ("Not reliable on older ARM hardware");
+ return;
+ }
+#endif
+
ctx = g_main_context_new ();
loop = g_main_loop_new (ctx, FALSE);
@@ -598,6 +606,14 @@ test_recursive_child_sources (void)
GMainLoop *loop;
GSource *parent, *child_b, *child_c, *end;
+#if defined(__arm__)
+ if (g_getenv ("DEB_ALLOW_FLAKY_TESTS") == NULL)
+ {
+ g_test_skip ("Not reliable on older ARM hardware");
+ return;
+ }
+#endif
+
ctx = g_main_context_new ();
loop = g_main_loop_new (ctx, FALSE);
diff --git a/glib/tests/timeout.c b/glib/tests/timeout.c
index 9e4d047..1ab8845 100644
--- a/glib/tests/timeout.c
+++ b/glib/tests/timeout.c
@@ -179,6 +179,15 @@ test_func (gpointer data)
static void
test_rounding (void)
{
+
+#if defined(__arm__)
+ if (g_getenv ("DEB_ALLOW_FLAKY_TESTS") == NULL)
+ {
+ g_test_skip ("Not reliable on older ARM hardware");
+ return;
+ }
+#endif
+
loop = g_main_loop_new (NULL, FALSE);
last_time = g_get_monotonic_time ();

View file

@ -1,25 +0,0 @@
From: Simon McVittie <smcv@debian.org>
Date: Sun, 24 Oct 2021 22:38:20 +0100
Subject: Skip memory-monitor-dbus test if not specifically requested
This seems to be unreliable, particularly on non-x86.
Bug-Debian: https://bugs.debian.org/995178
Forwarded: no
---
gio/tests/memory-monitor-dbus.py.in | 2 ++
1 file changed, 2 insertions(+)
diff --git a/gio/tests/memory-monitor-dbus.py.in b/gio/tests/memory-monitor-dbus.py.in
index bf32918..17862e3 100755
--- a/gio/tests/memory-monitor-dbus.py.in
+++ b/gio/tests/memory-monitor-dbus.py.in
@@ -39,6 +39,8 @@ try:
klass.start_system_bus()
klass.dbus_con = klass.get_dbus(True)
+ @unittest.skipIf('DEB_ALLOW_FLAKY_TESTS' not in os.environ,
+ 'https://bugs.debian.org/995178')
def setUp(self):
try:
Gio.MemoryMonitor

View file

@ -1,32 +0,0 @@
From: Iain Lane <laney@debian.org>
Date: Tue, 18 Mar 2014 15:43:35 +0000
Subject: Skip test which performs some unreliable floating point comparisons
[smcv: Modified to use g_test_skip() instead of omitting those test cases
completely, and allow them to be re-enabled with a Debian-specific
environment variable]
Co-authored-by: Simon McVittie <smcv@debian.org>
Bug: https://gitlab.gnome.org/GNOME/glib/issues/820
Forwarded: no
---
glib/tests/timer.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/glib/tests/timer.c b/glib/tests/timer.c
index 8ea5c1f..a4c1095 100644
--- a/glib/tests/timer.c
+++ b/glib/tests/timer.c
@@ -33,6 +33,12 @@ test_timer_basic (void)
volatile gdouble elapsed;
gulong micros;
+ if (g_getenv ("DEB_ALLOW_FLAKY_TESTS") == NULL)
+ {
+ g_test_skip ("Not reliable due to floating-point rounding (glib#820)");
+ return;
+ }
+
timer = g_timer_new ();
g_timer_start (timer);

View file

@ -1,48 +0,0 @@
From: Simon McVittie <smcv@debian.org>
Date: Fri, 4 Jan 2019 08:37:20 +0000
Subject: Skip unreliable gdbus-threading tests by default
test_threaded_singleton() test to reproduce a race condition between
last-unref of the global singleton GDBusConnection and g_bus_get_sync().
test_method_calls_in_thread() checks that multiple threads can all make
method calls to the same proxy.
However, test setup intermittently times out with:
# GLib-GIO-DEBUG: run 0: refcount is 2, sleeping
Bail out! GLib-GIO-FATAL-ERROR: connection had too many refs
The current theory upstream is that this might be a reference leak in
test_delivery_in_thread().
Furthermore, test teardown is now often failing when destroying the test
bus.
Demote these tests to be run as part of the "flaky" autopkgtests, but
not at build time or in the part of the autopkgtest run that gates
progress into testing.
Bug: https://gitlab.gnome.org/GNOME/glib/issues/1515
Forwarded: no
---
gio/tests/gdbus-threading.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/gio/tests/gdbus-threading.c b/gio/tests/gdbus-threading.c
index 9f3abc4..ec8867e 100644
--- a/gio/tests/gdbus-threading.c
+++ b/gio/tests/gdbus-threading.c
@@ -649,6 +649,12 @@ main (int argc,
g_test_init (&argc, &argv, NULL);
+ if (g_getenv ("DEB_ALLOW_FLAKY_TESTS") == NULL)
+ {
+ g_print("ok 1 # SKIP all gdbus-threading tests skipped because they are too unreliable (glib#1515)\n");
+ return 77;
+ }
+
session_bus_up ();
/* this is safe; testserver will exit once the bus goes away */

View file

@ -1,37 +0,0 @@
From: Simon McVittie <smcv@debian.org>
Date: Thu, 3 Jan 2019 09:01:03 +0000
Subject: closures test: Skip on arm* unless flaky tests are allowed
Choosing the right number of iterations to avoid either taking literally
hours on some hardware, or getting spurious failures when one thread
starves another, seems to be too hard to get right in practice.
Make this test opt-in so that its failures aren't release-critical.
We can run it as a separate autopkgtest that is marked flaky.
Signed-off-by: Simon McVittie <smcv@debian.org>
Bug-Debian: https://bugs.debian.org/880883
Bug-Debian: https://bugs.debian.org/917983
Forwarded: not-needed
---
gobject/tests/closure-refcount.c | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/gobject/tests/closure-refcount.c b/gobject/tests/closure-refcount.c
index 5a92005..73185f0 100644
--- a/gobject/tests/closure-refcount.c
+++ b/gobject/tests/closure-refcount.c
@@ -260,6 +260,14 @@ test_closure_refcount (void)
GTest *object;
guint i, n_iterations;
+#if defined(__aarch64__) || defined(__arm__)
+ if (g_getenv ("DEB_ALLOW_FLAKY_TESTS") != NULL)
+ {
+ g_print ("SKIP: Test is known to be flaky on arm* (#880883, #917983)\n");
+ return 0;
+ }
+#endif
+
object = g_object_new (G_TYPE_TEST, NULL);
closure = g_cclosure_new (G_CALLBACK (test_signal_handler), &test_data, destroy_data);

View file

@ -1,35 +0,0 @@
From: Simon McVittie <smcv@debian.org>
Date: Thu, 19 Nov 2020 10:44:39 +0000
Subject: gdbus-server-auth: Normally skip flaky DBUS_COOKIE_SHA1 tests
These intermittently fail on the buildds, but the failure cannot be
reproduced in a debugging environment.
We do not expect to use D-Bus over TCP on non-Windows platforms: we use
an AF_UNIX socket, which is much more robust and secure. However, when
using AF_UNIX, DBUS_COOKIE_SHA1 is unnecessary, because we can use the
more reliable EXTERNAL authentication.
Forwarded: not-needed
---
gio/tests/gdbus-server-auth.c | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/gio/tests/gdbus-server-auth.c b/gio/tests/gdbus-server-auth.c
index bd1443e..a231b0c 100644
--- a/gio/tests/gdbus-server-auth.c
+++ b/gio/tests/gdbus-server-auth.c
@@ -324,6 +324,13 @@ do_test_server_auth (InteropFlags flags)
}
#endif
+ if ((flags & (INTEROP_FLAGS_TCP | INTEROP_FLAGS_SHA1)) &&
+ g_getenv ("DEB_ALLOW_FLAKY_TESTS") == NULL)
+ {
+ g_test_skip ("https://gitlab.gnome.org/GNOME/glib/-/issues/2206");
+ goto out;
+ }
+
if (flags & INTEROP_FLAGS_ANONYMOUS)
server_flags |= G_DBUS_SERVER_FLAGS_AUTHENTICATION_ALLOW_ANONYMOUS;
if (flags & INTEROP_FLAGS_REQUIRE_SAME_USER)

View file

@ -1,29 +0,0 @@
From: Jeremy Bicha <jeremy.bicha@canonical.com>
Date: Wed, 23 Mar 2022 14:40:16 -0400
Subject: gdesktopappinfo: Recognize gnome-console as a terminal app
GNOME Console (installed as /usr/bin/kgx ) is the default
GNOME terminal app as of GNOME 42
Related to: https://gitlab.gnome.org/GNOME/glib/-/issues/338
But see https://gitlab.freedesktop.org/xdg/xdg-specs/-/merge_requests/46
for a more comprehensive way of handling issues around the default
terminal app
---
gio/gdesktopappinfo.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/gio/gdesktopappinfo.c b/gio/gdesktopappinfo.c
index 60d6deb..4a0b019 100644
--- a/gio/gdesktopappinfo.c
+++ b/gio/gdesktopappinfo.c
@@ -2672,6 +2672,8 @@ prepend_terminal_to_vector (int *argc,
}
else
{
+ if (check == NULL)
+ check = g_find_program_in_path ("kgx");
if (check == NULL)
check = g_find_program_in_path ("tilix");
if (check == NULL)

View file

@ -1,30 +0,0 @@
From: Simon McVittie <smcv@debian.org>
Date: Fri, 26 Jul 2019 23:49:03 +0100
Subject: gmenumodel test: Mark as flaky
This test has not had a great history of reliability.
Signed-off-by: Simon McVittie <smcv@debian.org>
Bug-Debian: https://bugs.debian.org/932678
Forwarded: no
---
gio/tests/gmenumodel.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/gio/tests/gmenumodel.c b/gio/tests/gmenumodel.c
index 492daf8..ed8828d 100644
--- a/gio/tests/gmenumodel.c
+++ b/gio/tests/gmenumodel.c
@@ -1160,6 +1160,12 @@ test_dbus_peer_subscriptions (void)
#else
PeerConnection peer;
+ if (g_getenv ("DEB_ALLOW_FLAKY_TESTS") == NULL)
+ {
+ g_test_skip ("Not reliable? #932678");
+ return;
+ }
+
peer_connection_up (&peer);
do_subscriptions (peer.server_connection, peer.client_connection);
peer_connection_down (&peer);

View file

@ -1,36 +0,0 @@
From: Simon McVittie <smcv@debian.org>
Date: Fri, 26 Jul 2019 23:51:39 +0100
Subject: gvariant test: Don't run at build-time on mips
DEB_ALLOW_FLAKY_TESTS is not quite right here, because we don't know
that the test would fail if left for long enough - the problem is that
it doesn't get there, because generating random floating-point numbers
is very slow on some of our mips hardware. However, it has the right
practical effect.
Signed-off-by: Simon McVittie <smcv@debian.org>
Bug: https://bugs.debian.org/932678
Forwarded: no
---
glib/tests/gvariant.c | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/glib/tests/gvariant.c b/glib/tests/gvariant.c
index 0110f26..1f30d23 100644
--- a/glib/tests/gvariant.c
+++ b/glib/tests/gvariant.c
@@ -2401,6 +2401,14 @@ test_fuzzes (gpointer data)
gdouble fuzziness;
int i;
+#ifdef __mips__
+ if (g_getenv ("DEB_ALLOW_FLAKY_TESTS") == NULL)
+ {
+ g_test_skip ("Extremely slow on some mips CPUs: #932678");
+ return;
+ }
+#endif
+
fuzziness = GPOINTER_TO_INT (data) / 100.;
for (i = 0; i < 200; i++)

View file

@ -1,117 +0,0 @@
From: Simon McVittie <smcv@debian.org>
Date: Tue, 25 Feb 2020 10:45:07 +0000
Subject: testfilemonitor: Skip if we are avoiding flaky tests
See https://gitlab.gnome.org/GNOME/glib/issues/1634
Signed-off-by: Simon McVittie <smcv@debian.org>
Forwarded: no
---
gio/tests/testfilemonitor.c | 38 +++++++++++++++++++++++++++++++++++++-
1 file changed, 37 insertions(+), 1 deletion(-)
diff --git a/gio/tests/testfilemonitor.c b/gio/tests/testfilemonitor.c
index 082f0db..7e7db90 100644
--- a/gio/tests/testfilemonitor.c
+++ b/gio/tests/testfilemonitor.c
@@ -32,6 +32,12 @@ setup (Fixture *fixture,
gchar *path = NULL;
GError *local_error = NULL;
+ if (g_getenv ("DEB_ALLOW_FLAKY_TESTS") == NULL)
+ {
+ g_test_skip ("https://gitlab.gnome.org/GNOME/glib/issues/1634");
+ return;
+ }
+
path = g_dir_make_tmp ("gio-test-testfilemonitor_XXXXXX", &local_error);
g_assert_no_error (local_error);
@@ -48,7 +54,9 @@ teardown (Fixture *fixture,
{
GError *local_error = NULL;
- g_file_delete (fixture->tmp_dir, NULL, &local_error);
+ if (fixture->tmp_dir != NULL)
+ g_file_delete (fixture->tmp_dir, NULL, &local_error);
+
g_assert_no_error (local_error);
g_clear_object (&fixture->tmp_dir);
}
@@ -375,6 +383,10 @@ test_atomic_replace (Fixture *fixture,
if (skip_win32 ())
return;
+ /* respect g_test_skip() during setup() */
+ if (g_test_failed ())
+ return;
+
data.step = 0;
data.events = NULL;
@@ -483,6 +495,10 @@ test_file_changes (Fixture *fixture,
if (skip_win32 ())
return;
+ /* respect g_test_skip() during setup() */
+ if (g_test_failed ())
+ return;
+
data.step = 0;
data.events = NULL;
@@ -603,6 +619,10 @@ test_dir_monitor (Fixture *fixture,
if (skip_win32 ())
return;
+ /* respect g_test_skip() during setup() */
+ if (g_test_failed ())
+ return;
+
data.step = 0;
data.events = NULL;
@@ -703,6 +723,10 @@ test_dir_non_existent (Fixture *fixture,
if (skip_win32 ())
return;
+ /* respect g_test_skip() during setup() */
+ if (g_test_failed ())
+ return;
+
data.step = 0;
data.events = NULL;
@@ -815,6 +839,10 @@ test_cross_dir_moves (Fixture *fixture,
if (skip_win32 ())
return;
+ /* respect g_test_skip() during setup() */
+ if (g_test_failed ())
+ return;
+
data[0].step = 0;
data[0].events = NULL;
@@ -984,6 +1012,10 @@ test_file_hard_links (Fixture *fixture,
GError *error = NULL;
TestData data;
+ /* respect g_test_skip() during setup() */
+ if (g_test_failed ())
+ return;
+
g_test_bug ("https://bugzilla.gnome.org/show_bug.cgi?id=755721");
if (skip_win32 ())
@@ -1043,6 +1075,10 @@ test_finalize_in_callback (Fixture *fixture,
GFile *file = NULL;
guint i;
+ /* respect g_test_skip() during setup() */
+ if (g_test_failed ())
+ return;
+
g_test_summary ("Test that finalization of a GFileMonitor in one of its "
"callbacks doesnt cause a deadlock.");
g_test_bug ("https://gitlab.gnome.org/GNOME/glib/-/issues/1941");

View file

@ -1,28 +0,0 @@
From: Simon McVittie <smcv@debian.org>
Date: Tue, 15 Feb 2022 20:42:53 +0000
Subject: tests: Skip debugcontroller test
This is known to be flaky upstream.
Forwarded: not-needed
---
gio/tests/debugcontroller.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/gio/tests/debugcontroller.c b/gio/tests/debugcontroller.c
index c20acd6..9c7216e 100644
--- a/gio/tests/debugcontroller.c
+++ b/gio/tests/debugcontroller.c
@@ -189,6 +189,12 @@ test_dbus_properties (void)
g_test_summary ("Test getting and setting properties on a #GDebugControllerDBus.");
+ if (g_getenv ("DEB_ALLOW_FLAKY_TESTS") == NULL)
+ {
+ g_test_skip ("https://gitlab.gnome.org/GNOME/glib/-/merge_requests/2486#note_1384102");
+ return;
+ }
+
/* Set up a test session bus and connection. Set up a separate second
* connection to simulate a remote peer. */
bus = g_test_dbus_new (G_TEST_DBUS_NONE);

View file

@ -1,36 +0,0 @@
From: Alexis Cruz <alexis.cruz@evin-ev.de>
Date: Tue, 4 Jul 2023 11:27:19 +0200
Subject: disable setting ACL attributes,
see https://code.evin.team/evin/ansible-managed-servers/issues/5
---
gio/gfile.c | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)
diff --git a/gio/gfile.c b/gio/gfile.c
index 1810e36..42ea204 100644
--- a/gio/gfile.c
+++ b/gio/gfile.c
@@ -3426,14 +3426,14 @@ file_copy_fallback (GFile *source,
/* Ignore errors here. Failure to copy metadata is not a hard error */
/* TODO: set these attributes /before/ we do the rename() on Unix */
- if (ret && do_set_attributes)
- {
- g_file_set_attributes_from_info (destination,
- info,
- G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
- cancellable,
- NULL);
- }
+ //if (ret && do_set_attributes)
+ // {
+ // g_file_set_attributes_from_info (destination,
+ // info,
+ // G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
+ // cancellable,
+ // NULL);
+ // }
g_clear_object (&info);

View file

@ -1,94 +0,0 @@
From 590f7a6b76b5a3695aa562c9c3ab244433b6624b Mon Sep 17 00:00:00 2001
From: William Manley <will@stb-tester.com>
Date: Tue, 23 Jun 2020 22:59:58 +0100
Subject: [PATCH 01/18] gvariant-core: Consolidate construction of
`GVariantSerialised`
So I only need to change it in one place.
This introduces no functional changes.
Helps: #2121
---
glib/gvariant-core.c | 49 ++++++++++++++++++++++----------------------
1 file changed, 25 insertions(+), 24 deletions(-)
--- a/glib/gvariant-core.c
+++ b/glib/gvariant-core.c
@@ -350,6 +350,27 @@ g_variant_ensure_size (GVariant *value)
}
/* < private >
+ * g_variant_to_serialised:
+ * @value: a #GVariant
+ *
+ * Gets a GVariantSerialised for a GVariant in state STATE_SERIALISED.
+ */
+inline static GVariantSerialised
+g_variant_to_serialised (GVariant *value)
+{
+ g_assert (value->state & STATE_SERIALISED);
+ {
+ GVariantSerialised serialised = {
+ value->type_info,
+ (gpointer) value->contents.serialised.data,
+ value->size,
+ value->depth,
+ };
+ return serialised;
+ }
+}
+
+/* < private >
* g_variant_serialise:
* @value: a #GVariant
* @data: an appropriately-sized buffer
@@ -1007,16 +1028,8 @@ g_variant_n_children (GVariant *value)
g_variant_lock (value);
if (value->state & STATE_SERIALISED)
- {
- GVariantSerialised serialised = {
- value->type_info,
- (gpointer) value->contents.serialised.data,
- value->size,
- value->depth,
- };
-
- n_children = g_variant_serialised_n_children (serialised);
- }
+ n_children = g_variant_serialised_n_children (
+ g_variant_to_serialised (value));
else
n_children = value->contents.tree.n_children;
@@ -1083,12 +1096,7 @@ g_variant_get_child_value (GVariant *val
}
{
- GVariantSerialised serialised = {
- value->type_info,
- (gpointer) value->contents.serialised.data,
- value->size,
- value->depth,
- };
+ GVariantSerialised serialised = g_variant_to_serialised (value);
GVariantSerialised s_child;
GVariant *child;
@@ -1201,14 +1209,7 @@ g_variant_is_normal_form (GVariant *valu
if (value->state & STATE_SERIALISED)
{
- GVariantSerialised serialised = {
- value->type_info,
- (gpointer) value->contents.serialised.data,
- value->size,
- value->depth
- };
-
- if (g_variant_serialised_is_normal (serialised))
+ if (g_variant_serialised_is_normal (g_variant_to_serialised (value)))
value->state |= STATE_TRUSTED;
}
else

View file

@ -1,201 +0,0 @@
From f8f5d8eefa06008aa8fe684069193dc3b1ae1b58 Mon Sep 17 00:00:00 2001
From: William Manley <will@stb-tester.com>
Date: Thu, 25 Jun 2020 17:08:21 +0100
Subject: [PATCH 02/18] gvariant-serialiser: Factor out functions for dealing
with framing offsets
This introduces no functional changes.
Helps: #2121
---
glib/gvariant-serialiser.c | 108 +++++++++++++++++++------------------
1 file changed, 57 insertions(+), 51 deletions(-)
--- a/glib/gvariant-serialiser.c
+++ b/glib/gvariant-serialiser.c
@@ -633,30 +633,62 @@ gvs_calculate_total_size (gsize body_siz
return body_size + 8 * offsets;
}
+struct Offsets
+{
+ gsize data_size;
+
+ guchar *array;
+ gsize length;
+ guint offset_size;
+
+ gboolean is_normal;
+};
+
static gsize
-gvs_variable_sized_array_n_children (GVariantSerialised value)
+gvs_offsets_get_offset_n (struct Offsets *offsets,
+ gsize n)
{
+ return gvs_read_unaligned_le (
+ offsets->array + (offsets->offset_size * n), offsets->offset_size);
+}
+
+static struct Offsets
+gvs_variable_sized_array_get_frame_offsets (GVariantSerialised value)
+{
+ struct Offsets out = { 0, };
gsize offsets_array_size;
- gsize offset_size;
gsize last_end;
if (value.size == 0)
- return 0;
-
- offset_size = gvs_get_offset_size (value.size);
+ {
+ out.is_normal = TRUE;
+ return out;
+ }
- last_end = gvs_read_unaligned_le (value.data + value.size -
- offset_size, offset_size);
+ out.offset_size = gvs_get_offset_size (value.size);
+ last_end = gvs_read_unaligned_le (value.data + value.size - out.offset_size,
+ out.offset_size);
if (last_end > value.size)
- return 0;
+ return out; /* offsets not normal */
offsets_array_size = value.size - last_end;
- if (offsets_array_size % offset_size)
- return 0;
+ if (offsets_array_size % out.offset_size)
+ return out; /* offsets not normal */
- return offsets_array_size / offset_size;
+ out.data_size = last_end;
+ out.array = value.data + last_end;
+ out.length = offsets_array_size / out.offset_size;
+ out.is_normal = TRUE;
+
+ return out;
+}
+
+static gsize
+gvs_variable_sized_array_n_children (GVariantSerialised value)
+{
+ return gvs_variable_sized_array_get_frame_offsets (value).length;
}
static GVariantSerialised
@@ -664,8 +696,9 @@ gvs_variable_sized_array_get_child (GVar
gsize index_)
{
GVariantSerialised child = { 0, };
- gsize offset_size;
- gsize last_end;
+
+ struct Offsets offsets = gvs_variable_sized_array_get_frame_offsets (value);
+
gsize start;
gsize end;
@@ -673,18 +706,11 @@ gvs_variable_sized_array_get_child (GVar
g_variant_type_info_ref (child.type_info);
child.depth = value.depth + 1;
- offset_size = gvs_get_offset_size (value.size);
-
- last_end = gvs_read_unaligned_le (value.data + value.size -
- offset_size, offset_size);
-
if (index_ > 0)
{
guint alignment;
- start = gvs_read_unaligned_le (value.data + last_end +
- (offset_size * (index_ - 1)),
- offset_size);
+ start = gvs_offsets_get_offset_n (&offsets, index_ - 1);
g_variant_type_info_query (child.type_info, &alignment, NULL);
start += (-start) & alignment;
@@ -692,11 +718,9 @@ gvs_variable_sized_array_get_child (GVar
else
start = 0;
- end = gvs_read_unaligned_le (value.data + last_end +
- (offset_size * index_),
- offset_size);
+ end = gvs_offsets_get_offset_n (&offsets, index_);
- if (start < end && end <= value.size && end <= last_end)
+ if (start < end && end <= value.size && end <= offsets.data_size)
{
child.data = value.data + start;
child.size = end - start;
@@ -768,34 +792,16 @@ static gboolean
gvs_variable_sized_array_is_normal (GVariantSerialised value)
{
GVariantSerialised child = { 0, };
- gsize offsets_array_size;
- guchar *offsets_array;
- guint offset_size;
guint alignment;
- gsize last_end;
- gsize length;
gsize offset;
gsize i;
- if (value.size == 0)
- return TRUE;
-
- offset_size = gvs_get_offset_size (value.size);
- last_end = gvs_read_unaligned_le (value.data + value.size -
- offset_size, offset_size);
+ struct Offsets offsets = gvs_variable_sized_array_get_frame_offsets (value);
- if (last_end > value.size)
+ if (!offsets.is_normal)
return FALSE;
- offsets_array_size = value.size - last_end;
-
- if (offsets_array_size % offset_size)
- return FALSE;
-
- offsets_array = value.data + value.size - offsets_array_size;
- length = offsets_array_size / offset_size;
-
- if (length == 0)
+ if (value.size != 0 && offsets.length == 0)
return FALSE;
child.type_info = g_variant_type_info_element (value.type_info);
@@ -803,14 +809,14 @@ gvs_variable_sized_array_is_normal (GVar
child.depth = value.depth + 1;
offset = 0;
- for (i = 0; i < length; i++)
+ for (i = 0; i < offsets.length; i++)
{
gsize this_end;
- this_end = gvs_read_unaligned_le (offsets_array + offset_size * i,
- offset_size);
+ this_end = gvs_read_unaligned_le (offsets.array + offsets.offset_size * i,
+ offsets.offset_size);
- if (this_end < offset || this_end > last_end)
+ if (this_end < offset || this_end > offsets.data_size)
return FALSE;
while (offset & alignment)
@@ -832,7 +838,7 @@ gvs_variable_sized_array_is_normal (GVar
offset = this_end;
}
- g_assert (offset == last_end);
+ g_assert (offset == offsets.data_size);
return TRUE;
}

View file

@ -1,87 +0,0 @@
From 5c27f22aff636766fbc5e49927fd28213629e840 Mon Sep 17 00:00:00 2001
From: Philip Withnall <pwithnall@endlessos.org>
Date: Tue, 25 Oct 2022 18:05:52 +0100
Subject: [PATCH 03/18] gvariant: Zero-initialise various GVariantSerialised
objects
The following few commits will add a couple of new fields to
`GVariantSerialised`, and they should be zero-filled by default.
Try and pre-empt that a bit by zero-filling `GVariantSerialised` by
default in a few places.
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
Helps: #2121
---
glib/gvariant.c | 2 +-
glib/tests/gvariant.c | 12 ++++++------
2 files changed, 7 insertions(+), 7 deletions(-)
--- a/glib/gvariant.c
+++ b/glib/gvariant.c
@@ -5988,7 +5988,7 @@ g_variant_byteswap (GVariant *value)
if (alignment)
/* (potentially) contains multi-byte numeric data */
{
- GVariantSerialised serialised;
+ GVariantSerialised serialised = { 0, };
GVariant *trusted;
GBytes *bytes;
--- a/glib/tests/gvariant.c
+++ b/glib/tests/gvariant.c
@@ -1438,7 +1438,7 @@ test_maybe (void)
for (flavour = 0; flavour < 8; flavour += alignment)
{
- GVariantSerialised serialised;
+ GVariantSerialised serialised = { 0, };
GVariantSerialised child;
serialised.type_info = type_info;
@@ -1562,7 +1562,7 @@ test_array (void)
for (flavour = 0; flavour < 8; flavour += alignment)
{
- GVariantSerialised serialised;
+ GVariantSerialised serialised = { 0, };
serialised.type_info = array_info;
serialised.data = flavoured_malloc (needed_size, flavour);
@@ -1726,7 +1726,7 @@ test_tuple (void)
for (flavour = 0; flavour < 8; flavour += alignment)
{
- GVariantSerialised serialised;
+ GVariantSerialised serialised = { 0, };
serialised.type_info = type_info;
serialised.data = flavoured_malloc (needed_size, flavour);
@@ -1821,7 +1821,7 @@ test_variant (void)
for (flavour = 0; flavour < 8; flavour += alignment)
{
- GVariantSerialised serialised;
+ GVariantSerialised serialised = { 0, };
GVariantSerialised child;
serialised.type_info = type_info;
@@ -2268,7 +2268,7 @@ serialise_tree (TreeInstance *tree
static void
test_byteswap (void)
{
- GVariantSerialised one, two;
+ GVariantSerialised one = { 0, }, two = { 0, };
TreeInstance *tree;
tree = tree_instance_new (NULL, 3);
@@ -2342,7 +2342,7 @@ test_serialiser_children (void)
static void
test_fuzz (gdouble *fuzziness)
{
- GVariantSerialised serialised;
+ GVariantSerialised serialised = { 0, };
TreeInstance *tree;
/* make an instance */

View file

@ -1,406 +0,0 @@
From c8067857f7c8fb369ecb30bb534b018b2e2b8f87 Mon Sep 17 00:00:00 2001
From: William Manley <will@stb-tester.com>
Date: Mon, 29 Jun 2020 16:59:44 +0100
Subject: [PATCH 04/18] =?UTF-8?q?gvariant:=20Don=E2=80=99t=20allow=20child?=
=?UTF-8?q?=20elements=20to=20overlap=20with=20each=20other?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
If different elements of a variable sized array can overlap with each
other then we can cause a `GVariant` to normalise to a much larger type.
This commit changes the behaviour of `GVariant` with non-normal form data. If
an invalid frame offset is found all subsequent elements are given their
default value.
When retrieving an element at index `n` we scan the frame offsets up to index
`n` and if they are not in order we return an element with the default value
for that type. This guarantees that elements don't overlap with each
other. We remember the offset we've scanned up to so we don't need to
repeat this work on subsequent accesses. We skip these checks for trusted
data.
Unfortunately this makes random access of untrusted data O(n) — at least
on first access. It doesn't affect the algorithmic complexity of accessing
elements in order, such as when using the `GVariantIter` interface. Also:
the cost of validation will be amortised as the `GVariant` instance is
continued to be used.
I've implemented this with 4 different functions, 1 for each element size,
rather than looping calling `gvs_read_unaligned_le` in the hope that the
compiler will find it easy to optimise and should produce fairly tight
code.
Fixes: #2121
---
glib/gvariant-core.c | 35 ++++++++++++++++
glib/gvariant-serialiser.c | 86 ++++++++++++++++++++++++++++++++++++--
glib/gvariant-serialiser.h | 9 ++++
glib/tests/gvariant.c | 45 ++++++++++++++++++++
4 files changed, 172 insertions(+), 3 deletions(-)
--- a/glib/gvariant-core.c
+++ b/glib/gvariant-core.c
@@ -65,6 +65,7 @@ struct _GVariant
{
GBytes *bytes;
gconstpointer data;
+ gsize ordered_offsets_up_to;
} serialised;
struct
@@ -162,6 +163,24 @@ struct _GVariant
* if .data pointed to the appropriate number of nul
* bytes.
*
+ * .ordered_offsets_up_to: If ordered_offsets_up_to == n this means that all
+ * the frame offsets up to and including the frame
+ * offset determining the end of element n are in
+ * order. This guarantees that the bytes of element
+ * n don't overlap with any previous element.
+ *
+ * For trusted data this is set to G_MAXSIZE and we
+ * don't check that the frame offsets are in order.
+ *
+ * Note: This doesn't imply the offsets are good in
+ * any way apart from their ordering. In particular
+ * offsets may be out of bounds for this value or
+ * may imply that the data overlaps the frame
+ * offsets themselves.
+ *
+ * This field is only relevant for arrays of non
+ * fixed width types.
+ *
* .tree: Only valid when the instance is in tree form.
*
* Note that accesses from other threads could result in
@@ -365,6 +384,7 @@ g_variant_to_serialised (GVariant *value
(gpointer) value->contents.serialised.data,
value->size,
value->depth,
+ value->contents.serialised.ordered_offsets_up_to,
};
return serialised;
}
@@ -396,6 +416,7 @@ g_variant_serialise (GVariant *value,
serialised.size = value->size;
serialised.data = data;
serialised.depth = value->depth;
+ serialised.ordered_offsets_up_to = 0;
children = (gpointer *) value->contents.tree.children;
n_children = value->contents.tree.n_children;
@@ -439,6 +460,15 @@ g_variant_fill_gvs (GVariantSerialised *
g_assert (serialised->size == value->size);
serialised->depth = value->depth;
+ if (value->state & STATE_SERIALISED)
+ {
+ serialised->ordered_offsets_up_to = value->contents.serialised.ordered_offsets_up_to;
+ }
+ else
+ {
+ serialised->ordered_offsets_up_to = 0;
+ }
+
if (serialised->data)
/* g_variant_store() is a public API, so it
* it will reacquire the lock if it needs to.
@@ -481,6 +511,7 @@ g_variant_ensure_serialised (GVariant *v
bytes = g_bytes_new_take (data, value->size);
value->contents.serialised.data = g_bytes_get_data (bytes, NULL);
value->contents.serialised.bytes = bytes;
+ value->contents.serialised.ordered_offsets_up_to = G_MAXSIZE;
value->state |= STATE_SERIALISED;
}
}
@@ -561,6 +592,7 @@ g_variant_new_from_bytes (const GVariant
serialised.type_info = value->type_info;
serialised.data = (guchar *) g_bytes_get_data (bytes, &serialised.size);
serialised.depth = 0;
+ serialised.ordered_offsets_up_to = trusted ? G_MAXSIZE : 0;
if (!g_variant_serialised_check (serialised))
{
@@ -611,6 +643,8 @@ g_variant_new_from_bytes (const GVariant
value->contents.serialised.data = g_bytes_get_data (bytes, &value->size);
}
+ value->contents.serialised.ordered_offsets_up_to = trusted ? G_MAXSIZE : 0;
+
g_clear_pointer (&owned_bytes, g_bytes_unref);
return value;
@@ -1130,6 +1164,7 @@ g_variant_get_child_value (GVariant *val
child->contents.serialised.bytes =
g_bytes_ref (value->contents.serialised.bytes);
child->contents.serialised.data = s_child.data;
+ child->contents.serialised.ordered_offsets_up_to = s_child.ordered_offsets_up_to;
return child;
}
--- a/glib/gvariant-serialiser.c
+++ b/glib/gvariant-serialiser.c
@@ -1,6 +1,7 @@
/*
* Copyright © 2007, 2008 Ryan Lortie
* Copyright © 2010 Codethink Limited
+ * Copyright © 2020 William Manley
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -264,6 +265,7 @@ gvs_fixed_sized_maybe_get_child (GVarian
value.type_info = g_variant_type_info_element (value.type_info);
g_variant_type_info_ref (value.type_info);
value.depth++;
+ value.ordered_offsets_up_to = 0;
return value;
}
@@ -295,7 +297,7 @@ gvs_fixed_sized_maybe_serialise (GVarian
{
if (n_children)
{
- GVariantSerialised child = { NULL, value.data, value.size, value.depth + 1 };
+ GVariantSerialised child = { NULL, value.data, value.size, value.depth + 1, 0 };
gvs_filler (&child, children[0]);
}
@@ -317,6 +319,7 @@ gvs_fixed_sized_maybe_is_normal (GVarian
/* proper element size: "Just". recurse to the child. */
value.type_info = g_variant_type_info_element (value.type_info);
value.depth++;
+ value.ordered_offsets_up_to = 0;
return g_variant_serialised_is_normal (value);
}
@@ -358,6 +361,7 @@ gvs_variable_sized_maybe_get_child (GVar
value.data = NULL;
value.depth++;
+ value.ordered_offsets_up_to = 0;
return value;
}
@@ -388,7 +392,7 @@ gvs_variable_sized_maybe_serialise (GVar
{
if (n_children)
{
- GVariantSerialised child = { NULL, value.data, value.size - 1, value.depth + 1 };
+ GVariantSerialised child = { NULL, value.data, value.size - 1, value.depth + 1, 0 };
/* write the data for the child. */
gvs_filler (&child, children[0]);
@@ -408,6 +412,7 @@ gvs_variable_sized_maybe_is_normal (GVar
value.type_info = g_variant_type_info_element (value.type_info);
value.size--;
value.depth++;
+ value.ordered_offsets_up_to = 0;
return g_variant_serialised_is_normal (value);
}
@@ -691,6 +696,32 @@ gvs_variable_sized_array_n_children (GVa
return gvs_variable_sized_array_get_frame_offsets (value).length;
}
+/* Find the index of the first out-of-order element in @data, assuming that
+ * @data is an array of elements of given @type, starting at index @start and
+ * containing a further @len-@start elements. */
+#define DEFINE_FIND_UNORDERED(type) \
+ static gsize \
+ find_unordered_##type (const guint8 *data, gsize start, gsize len) \
+ { \
+ gsize off; \
+ type current, previous; \
+ \
+ memcpy (&previous, data + start * sizeof (current), sizeof (current)); \
+ for (off = (start + 1) * sizeof (current); off < len * sizeof (current); off += sizeof (current)) \
+ { \
+ memcpy (&current, data + off, sizeof (current)); \
+ if (current < previous) \
+ break; \
+ previous = current; \
+ } \
+ return off / sizeof (current) - 1; \
+ }
+
+DEFINE_FIND_UNORDERED (guint8);
+DEFINE_FIND_UNORDERED (guint16);
+DEFINE_FIND_UNORDERED (guint32);
+DEFINE_FIND_UNORDERED (guint64);
+
static GVariantSerialised
gvs_variable_sized_array_get_child (GVariantSerialised value,
gsize index_)
@@ -706,6 +737,49 @@ gvs_variable_sized_array_get_child (GVar
g_variant_type_info_ref (child.type_info);
child.depth = value.depth + 1;
+ /* If the requested @index_ is beyond the set of indices whose framing offsets
+ * have been checked, check the remaining offsets to see whether theyre
+ * normal (in order, no overlapping array elements). */
+ if (index_ > value.ordered_offsets_up_to)
+ {
+ switch (offsets.offset_size)
+ {
+ case 1:
+ {
+ value.ordered_offsets_up_to = find_unordered_guint8 (
+ offsets.array, value.ordered_offsets_up_to, index_ + 1);
+ break;
+ }
+ case 2:
+ {
+ value.ordered_offsets_up_to = find_unordered_guint16 (
+ offsets.array, value.ordered_offsets_up_to, index_ + 1);
+ break;
+ }
+ case 4:
+ {
+ value.ordered_offsets_up_to = find_unordered_guint32 (
+ offsets.array, value.ordered_offsets_up_to, index_ + 1);
+ break;
+ }
+ case 8:
+ {
+ value.ordered_offsets_up_to = find_unordered_guint64 (
+ offsets.array, value.ordered_offsets_up_to, index_ + 1);
+ break;
+ }
+ default:
+ /* gvs_get_offset_size() only returns maximum 8 */
+ g_assert_not_reached ();
+ }
+ }
+
+ if (index_ > value.ordered_offsets_up_to)
+ {
+ /* Offsets are invalid somewhere, so return an empty child. */
+ return child;
+ }
+
if (index_ > 0)
{
guint alignment;
@@ -840,6 +914,9 @@ gvs_variable_sized_array_is_normal (GVar
g_assert (offset == offsets.data_size);
+ /* All offsets have now been checked. */
+ value.ordered_offsets_up_to = G_MAXSIZE;
+
return TRUE;
}
@@ -1072,7 +1149,7 @@ gvs_tuple_is_normal (GVariantSerialised
for (i = 0; i < length; i++)
{
const GVariantMemberInfo *member_info;
- GVariantSerialised child;
+ GVariantSerialised child = { 0, };
gsize fixed_size;
guint alignment;
gsize end;
@@ -1132,6 +1209,9 @@ gvs_tuple_is_normal (GVariantSerialised
offset = end;
}
+ /* All element bounds have been checked above. */
+ value.ordered_offsets_up_to = G_MAXSIZE;
+
{
gsize fixed_size;
guint alignment;
--- a/glib/gvariant-serialiser.h
+++ b/glib/gvariant-serialiser.h
@@ -29,6 +29,15 @@ typedef struct
guchar *data;
gsize size;
gsize depth; /* same semantics as GVariant.depth */
+
+ /* If ordered_offsets_up_to == n this means that all the frame offsets up to and
+ * including the frame offset determining the end of element n are in order.
+ * This guarantees that the bytes of element n don't overlap with any previous
+ * element.
+ *
+ * This is both read and set by g_variant_serialised_get_child for arrays of
+ * non-fixed-width types */
+ gsize ordered_offsets_up_to;
} GVariantSerialised;
/* deserialization */
--- a/glib/tests/gvariant.c
+++ b/glib/tests/gvariant.c
@@ -1,5 +1,6 @@
/*
* Copyright © 2010 Codethink Limited
+ * Copyright © 2020 William Manley
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -1279,6 +1280,7 @@ random_instance_filler (GVariantSerialis
serialised->size = instance->size;
serialised->depth = 0;
+ serialised->ordered_offsets_up_to = 0;
g_assert_true (serialised->type_info == instance->type_info);
g_assert_cmpuint (serialised->size, ==, instance->size);
@@ -5031,6 +5033,47 @@ test_normal_checking_array_offsets (void
g_variant_unref (variant);
}
+/* This is a regression test that we can't have non-normal values that take up
+ * significantly more space than the normal equivalent, by specifying the
+ * offset table entries so that array elements overlap.
+ *
+ * See https://gitlab.gnome.org/GNOME/glib/-/issues/2121#note_832242 */
+static void
+test_normal_checking_array_offsets2 (void)
+{
+ const guint8 data[] = {
+ 'h', 'i', '\0',
+ 0x03, 0x00, 0x03,
+ 0x06, 0x00, 0x06,
+ 0x09, 0x00, 0x09,
+ 0x0c, 0x00, 0x0c,
+ 0x0f, 0x00, 0x0f,
+ 0x12, 0x00, 0x12,
+ 0x15, 0x00, 0x15,
+ };
+ gsize size = sizeof (data);
+ const GVariantType *aaaaaaas = G_VARIANT_TYPE ("aaaaaaas");
+ GVariant *variant = NULL;
+ GVariant *normal_variant = NULL;
+ GVariant *expected = NULL;
+
+ variant = g_variant_new_from_data (aaaaaaas, data, size, FALSE, NULL, NULL);
+ g_assert_nonnull (variant);
+
+ normal_variant = g_variant_get_normal_form (variant);
+ g_assert_nonnull (normal_variant);
+ g_assert_cmpuint (g_variant_get_size (normal_variant), <=, size * 2);
+
+ expected = g_variant_new_parsed (
+ "[[[[[[['hi', '', ''], [], []], [], []], [], []], [], []], [], []], [], []]");
+ g_assert_cmpvariant (expected, variant);
+ g_assert_cmpvariant (expected, normal_variant);
+
+ g_variant_unref (expected);
+ g_variant_unref (normal_variant);
+ g_variant_unref (variant);
+}
+
/* Test that a tuple with invalidly large values in its offset table is
* normalised successfully without looping infinitely. */
static void
@@ -5197,6 +5240,8 @@ main (int argc, char **argv)
test_normal_checking_tuples);
g_test_add_func ("/gvariant/normal-checking/array-offsets",
test_normal_checking_array_offsets);
+ g_test_add_func ("/gvariant/normal-checking/array-offsets2",
+ test_normal_checking_array_offsets2);
g_test_add_func ("/gvariant/normal-checking/tuple-offsets",
test_normal_checking_tuple_offsets);
g_test_add_func ("/gvariant/normal-checking/empty-object-path",

View file

@ -1,104 +0,0 @@
From 66e7c10aa1ec3102c49186f83671a5f0461ffbc0 Mon Sep 17 00:00:00 2001
From: Philip Withnall <pwithnall@endlessos.org>
Date: Fri, 7 Jan 2022 15:03:52 +0000
Subject: [PATCH 05/18] gvariant-serialiser: Factor out code to get bounds of a
tuple member
This introduces no functional changes.
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
Helps: #2121
---
glib/gvariant-serialiser.c | 73 ++++++++++++++++++++++++--------------
1 file changed, 46 insertions(+), 27 deletions(-)
--- a/glib/gvariant-serialiser.c
+++ b/glib/gvariant-serialiser.c
@@ -942,6 +942,51 @@ gvs_variable_sized_array_is_normal (GVar
* for the tuple. See the notes in gvarianttypeinfo.h.
*/
+static void
+gvs_tuple_get_member_bounds (GVariantSerialised value,
+ gsize index_,
+ gsize offset_size,
+ gsize *out_member_start,
+ gsize *out_member_end)
+{
+ const GVariantMemberInfo *member_info;
+ gsize member_start, member_end;
+
+ member_info = g_variant_type_info_member_info (value.type_info, index_);
+
+ if (member_info->i + 1)
+ member_start = gvs_read_unaligned_le (value.data + value.size -
+ offset_size * (member_info->i + 1),
+ offset_size);
+ else
+ member_start = 0;
+
+ member_start += member_info->a;
+ member_start &= member_info->b;
+ member_start |= member_info->c;
+
+ if (member_info->ending_type == G_VARIANT_MEMBER_ENDING_LAST)
+ member_end = value.size - offset_size * (member_info->i + 1);
+
+ else if (member_info->ending_type == G_VARIANT_MEMBER_ENDING_FIXED)
+ {
+ gsize fixed_size;
+
+ g_variant_type_info_query (member_info->type_info, NULL, &fixed_size);
+ member_end = member_start + fixed_size;
+ }
+
+ else /* G_VARIANT_MEMBER_ENDING_OFFSET */
+ member_end = gvs_read_unaligned_le (value.data + value.size -
+ offset_size * (member_info->i + 2),
+ offset_size);
+
+ if (out_member_start != NULL)
+ *out_member_start = member_start;
+ if (out_member_end != NULL)
+ *out_member_end = member_end;
+}
+
static gsize
gvs_tuple_n_children (GVariantSerialised value)
{
@@ -997,33 +1042,7 @@ gvs_tuple_get_child (GVariantSerialised
}
}
- if (member_info->i + 1)
- start = gvs_read_unaligned_le (value.data + value.size -
- offset_size * (member_info->i + 1),
- offset_size);
- else
- start = 0;
-
- start += member_info->a;
- start &= member_info->b;
- start |= member_info->c;
-
- if (member_info->ending_type == G_VARIANT_MEMBER_ENDING_LAST)
- end = value.size - offset_size * (member_info->i + 1);
-
- else if (member_info->ending_type == G_VARIANT_MEMBER_ENDING_FIXED)
- {
- gsize fixed_size;
-
- g_variant_type_info_query (child.type_info, NULL, &fixed_size);
- end = start + fixed_size;
- child.size = fixed_size;
- }
-
- else /* G_VARIANT_MEMBER_ENDING_OFFSET */
- end = gvs_read_unaligned_le (value.data + value.size -
- offset_size * (member_info->i + 2),
- offset_size);
+ gvs_tuple_get_member_bounds (value, index_, offset_size, &start, &end);
/* The child should not extend into the offset table. */
if (index_ != g_variant_type_info_n_members (value.type_info) - 1)

View file

@ -1,74 +0,0 @@
From a62a6b5d3e53b30a4628db2a077ab9ed03605748 Mon Sep 17 00:00:00 2001
From: Philip Withnall <pwithnall@endlessos.org>
Date: Fri, 7 Jan 2022 16:37:29 +0000
Subject: [PATCH 06/18] gvariant-serialiser: Rework child size calculation
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
This reduces a few duplicate calls to `g_variant_type_info_query()` and
explains why theyre needed.
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
Helps: #2121
---
glib/gvariant-serialiser.c | 31 +++++++++----------------------
1 file changed, 9 insertions(+), 22 deletions(-)
--- a/glib/gvariant-serialiser.c
+++ b/glib/gvariant-serialiser.c
@@ -1007,14 +1007,18 @@ gvs_tuple_get_child (GVariantSerialised
child.depth = value.depth + 1;
offset_size = gvs_get_offset_size (value.size);
+ /* Ensure the size is set for fixed-sized children, or
+ * g_variant_serialised_check() will fail, even if we return
+ * (child.data == NULL) to indicate an error. */
+ if (member_info->ending_type == G_VARIANT_MEMBER_ENDING_FIXED)
+ g_variant_type_info_query (child.type_info, NULL, &child.size);
+
/* tuples are the only (potentially) fixed-sized containers, so the
* only ones that have to deal with the possibility of having %NULL
* data with a non-zero %size if errors occurred elsewhere.
*/
if G_UNLIKELY (value.data == NULL && value.size != 0)
{
- g_variant_type_info_query (child.type_info, NULL, &child.size);
-
/* this can only happen in fixed-sized tuples,
* so the child must also be fixed sized.
*/
@@ -1032,29 +1036,12 @@ gvs_tuple_get_child (GVariantSerialised
else
{
if (offset_size * (member_info->i + 1) > value.size)
- {
- /* if the child is fixed size, return its size.
- * if child is not fixed-sized, return size = 0.
- */
- g_variant_type_info_query (child.type_info, NULL, &child.size);
-
- return child;
- }
+ return child;
}
- gvs_tuple_get_member_bounds (value, index_, offset_size, &start, &end);
-
/* The child should not extend into the offset table. */
- if (index_ != g_variant_type_info_n_members (value.type_info) - 1)
- {
- GVariantSerialised last_child;
- last_child = gvs_tuple_get_child (value,
- g_variant_type_info_n_members (value.type_info) - 1);
- last_end = last_child.data + last_child.size - value.data;
- g_variant_type_info_unref (last_child.type_info);
- }
- else
- last_end = end;
+ gvs_tuple_get_member_bounds (value, index_, offset_size, &start, &end);
+ gvs_tuple_get_member_bounds (value, g_variant_type_info_n_members (value.type_info) - 1, offset_size, NULL, &last_end);
if (start < end && end <= value.size && end <= last_end)
{

View file

@ -1,382 +0,0 @@
From 2d55b3b74b1bc256e91a9d0d59120570376e6acc Mon Sep 17 00:00:00 2001
From: Philip Withnall <pwithnall@endlessos.org>
Date: Fri, 7 Jan 2022 16:42:14 +0000
Subject: [PATCH 07/18] =?UTF-8?q?gvariant:=20Don=E2=80=99t=20allow=20child?=
=?UTF-8?q?=20elements=20of=20a=20tuple=20to=20overlap=20each=20other?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
This is similar to the earlier commit which prevents child elements of a
variable-sized array from overlapping each other, but this time for
tuples. It is based heavily on ideas by William Manley.
Tuples are slightly different from variable-sized arrays in that they
contain a mixture of fixed and variable sized elements. All but one of
the variable sized elements have an entry in the frame offsets table.
This means that if we were to just check the ordering of the frame
offsets table, the variable sized elements could still overlap
interleaving fixed sized elements, which would be bad.
Therefore we have to check the elements rather than the frame offsets.
The logic of checking the elements up to the index currently being
requested, and caching the result in `ordered_offsets_up_to`, means that
the algorithmic cost implications are the same for this commit as for
variable-sized arrays: an O(N) cost for these checks is amortised out
over N accesses to O(1) per access.
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
Fixes: #2121
---
glib/gvariant-core.c | 6 +-
glib/gvariant-serialiser.c | 40 ++++++++
glib/gvariant-serialiser.h | 7 +-
glib/gvariant.c | 1 +
glib/tests/gvariant.c | 181 +++++++++++++++++++++++++++++++++++++
5 files changed, 232 insertions(+), 3 deletions(-)
--- a/glib/gvariant-core.c
+++ b/glib/gvariant-core.c
@@ -1,6 +1,7 @@
/*
* Copyright © 2007, 2008 Ryan Lortie
* Copyright © 2010 Codethink Limited
+ * Copyright © 2022 Endless OS Foundation, LLC
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -179,7 +180,7 @@ struct _GVariant
* offsets themselves.
*
* This field is only relevant for arrays of non
- * fixed width types.
+ * fixed width types and for tuples.
*
* .tree: Only valid when the instance is in tree form.
*
@@ -1139,6 +1140,9 @@ g_variant_get_child_value (GVariant *val
*/
s_child = g_variant_serialised_get_child (serialised, index_);
+ /* Update the cached ordered_offsets_up_to, since @serialised will be thrown away when this function exits */
+ value->contents.serialised.ordered_offsets_up_to = MAX (value->contents.serialised.ordered_offsets_up_to, serialised.ordered_offsets_up_to);
+
/* Check whether this would cause nesting too deep. If so, return a fake
* child. The only situation we expect this to happen in is with a variant,
* as all other deeply-nested types have a static type, and hence should
--- a/glib/gvariant-serialiser.c
+++ b/glib/gvariant-serialiser.c
@@ -942,6 +942,10 @@ gvs_variable_sized_array_is_normal (GVar
* for the tuple. See the notes in gvarianttypeinfo.h.
*/
+/* Note: This doesnt guarantee that @out_member_end >= @out_member_start; that
+ * condition may not hold true for invalid serialised variants. The caller is
+ * responsible for checking the returned values and handling invalid ones
+ * appropriately. */
static void
gvs_tuple_get_member_bounds (GVariantSerialised value,
gsize index_,
@@ -1028,6 +1032,42 @@ gvs_tuple_get_child (GVariantSerialised
return child;
}
+ /* If the requested @index_ is beyond the set of indices whose framing offsets
+ * have been checked, check the remaining offsets to see whether theyre
+ * normal (in order, no overlapping tuple elements).
+ *
+ * Unlike the checks in gvs_variable_sized_array_get_child(), we have to check
+ * all the tuple *elements* here, not just all the framing offsets, since
+ * tuples contain a mix of elements which use framing offsets and ones which
+ * dont. None of them are allowed to overlap. */
+ if (index_ > value.ordered_offsets_up_to)
+ {
+ gsize i, prev_i_end = 0;
+
+ if (value.ordered_offsets_up_to > 0)
+ gvs_tuple_get_member_bounds (value, value.ordered_offsets_up_to - 1, offset_size, NULL, &prev_i_end);
+
+ for (i = value.ordered_offsets_up_to; i <= index_; i++)
+ {
+ gsize i_start, i_end;
+
+ gvs_tuple_get_member_bounds (value, i, offset_size, &i_start, &i_end);
+
+ if (i_start > i_end || i_start < prev_i_end || i_end > value.size)
+ break;
+
+ prev_i_end = i_end;
+ }
+
+ value.ordered_offsets_up_to = i - 1;
+ }
+
+ if (index_ > value.ordered_offsets_up_to)
+ {
+ /* Offsets are invalid somewhere, so return an empty child. */
+ return child;
+ }
+
if (member_info->ending_type == G_VARIANT_MEMBER_ENDING_OFFSET)
{
if (offset_size * (member_info->i + 2) > value.size)
--- a/glib/gvariant-serialiser.h
+++ b/glib/gvariant-serialiser.h
@@ -35,8 +35,11 @@ typedef struct
* This guarantees that the bytes of element n don't overlap with any previous
* element.
*
- * This is both read and set by g_variant_serialised_get_child for arrays of
- * non-fixed-width types */
+ * This is both read and set by g_variant_serialised_get_child() for arrays of
+ * non-fixed-width types, and for tuples.
+ *
+ * Even when dealing with tuples, @ordered_offsets_up_to is an element index,
+ * rather than an index into the frame offsets. */
gsize ordered_offsets_up_to;
} GVariantSerialised;
--- a/glib/gvariant.c
+++ b/glib/gvariant.c
@@ -5997,6 +5997,7 @@ g_variant_byteswap (GVariant *value)
serialised.size = g_variant_get_size (trusted);
serialised.data = g_malloc (serialised.size);
serialised.depth = g_variant_get_depth (trusted);
+ serialised.ordered_offsets_up_to = G_MAXSIZE; /* operating on the normal form */
g_variant_store (trusted, serialised.data);
g_variant_unref (trusted);
--- a/glib/tests/gvariant.c
+++ b/glib/tests/gvariant.c
@@ -1,6 +1,7 @@
/*
* Copyright © 2010 Codethink Limited
* Copyright © 2020 William Manley
+ * Copyright © 2022 Endless OS Foundation, LLC
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -1447,6 +1448,7 @@ test_maybe (void)
serialised.data = flavoured_malloc (needed_size, flavour);
serialised.size = needed_size;
serialised.depth = 0;
+ serialised.ordered_offsets_up_to = 0;
g_variant_serialiser_serialise (serialised,
random_instance_filler,
@@ -1570,6 +1572,7 @@ test_array (void)
serialised.data = flavoured_malloc (needed_size, flavour);
serialised.size = needed_size;
serialised.depth = 0;
+ serialised.ordered_offsets_up_to = 0;
g_variant_serialiser_serialise (serialised, random_instance_filler,
(gpointer *) instances, n_children);
@@ -1734,6 +1737,7 @@ test_tuple (void)
serialised.data = flavoured_malloc (needed_size, flavour);
serialised.size = needed_size;
serialised.depth = 0;
+ serialised.ordered_offsets_up_to = 0;
g_variant_serialiser_serialise (serialised, random_instance_filler,
(gpointer *) instances, n_children);
@@ -1830,6 +1834,7 @@ test_variant (void)
serialised.data = flavoured_malloc (needed_size, flavour);
serialised.size = needed_size;
serialised.depth = 0;
+ serialised.ordered_offsets_up_to = 0;
g_variant_serialiser_serialise (serialised, random_instance_filler,
(gpointer *) &instance, 1);
@@ -5098,6 +5103,176 @@ test_normal_checking_tuple_offsets (void
g_variant_unref (variant);
}
+/* This is a regression test that we can't have non-normal values that take up
+ * significantly more space than the normal equivalent, by specifying the
+ * offset table entries so that tuple elements overlap.
+ *
+ * See https://gitlab.gnome.org/GNOME/glib/-/issues/2121#note_838503 and
+ * https://gitlab.gnome.org/GNOME/glib/-/issues/2121#note_838513 */
+static void
+test_normal_checking_tuple_offsets2 (void)
+{
+ const GVariantType *data_type = G_VARIANT_TYPE ("(yyaiyyaiyy)");
+ const guint8 data[] = {
+ 0x12, 0x34, 0x56, 0x78, 0x01,
+ /*
+ ^───────────────────┘
+
+ ^^^^^^^^^^ 1st yy
+ ^^^^^^^^^^ 2nd yy
+ ^^^^^^^^^^ 3rd yy
+ ^^^^ Framing offsets
+ */
+
+ /* If this variant was encoded normally, it would be something like this:
+ * 0x12, 0x34, pad, pad, [array bytes], 0x56, 0x78, pad, pad, [array bytes], 0x9A, 0xBC, 0xXX
+ * ^─────────────────────────────────────────────────────┘
+ *
+ * ^^^^^^^^^^ 1st yy
+ * ^^^^^^^^^^ 2nd yy
+ * ^^^^^^^^^^ 3rd yy
+ * ^^^^ Framing offsets
+ */
+ };
+ gsize size = sizeof (data);
+ GVariant *variant = NULL;
+ GVariant *normal_variant = NULL;
+ GVariant *expected = NULL;
+
+ variant = g_variant_new_from_data (data_type, data, size, FALSE, NULL, NULL);
+ g_assert_nonnull (variant);
+
+ normal_variant = g_variant_get_normal_form (variant);
+ g_assert_nonnull (normal_variant);
+ g_assert_cmpuint (g_variant_get_size (normal_variant), <=, size * 3);
+
+ expected = g_variant_new_parsed (
+ "@(yyaiyyaiyy) (0x12, 0x34, [], 0x00, 0x00, [], 0x00, 0x00)");
+ g_assert_cmpvariant (expected, variant);
+ g_assert_cmpvariant (expected, normal_variant);
+
+ g_variant_unref (expected);
+ g_variant_unref (normal_variant);
+ g_variant_unref (variant);
+}
+
+/* This is a regression test that overlapping entries in the offset table are
+ * decoded consistently, even though theyre non-normal.
+ *
+ * See https://gitlab.gnome.org/GNOME/glib/-/issues/2121#note_910935 */
+static void
+test_normal_checking_tuple_offsets3 (void)
+{
+ /* The expected decoding of this non-normal byte stream is complex. See
+ * section 2.7.3 (Handling Non-Normal Serialised Data) of the GVariant
+ * specification.
+ *
+ * The rule “Child Values Overlapping Framing Offsets” from the specification
+ * says that the first `ay` must be decoded as `[0x01]` even though it
+ * overlaps the first byte of the offset table. However, since commit
+ * 7eedcd76f7d5b8c98fa60013e1fe6e960bf19df3, GLib explicitly doesnt allow
+ * this as its exploitable. So the first `ay` must be given a default value.
+ *
+ * The second and third `ay`s must be given default values because of rule
+ * “End Boundary Precedes Start Boundary”.
+ *
+ * The `i` must be given a default value because of rule “Start or End
+ * Boundary of a Child Falls Outside the Container”.
+ */
+ const GVariantType *data_type = G_VARIANT_TYPE ("(ayayiay)");
+ const guint8 data[] = {
+ 0x01, 0x00, 0x02,
+ /*
+ ^──┘
+
+ ^^^^^^^^^^ 1st ay, bytes 0-2 (but given a default value anyway, see above)
+ 2nd ay, bytes 2-0
+ i, bytes 0-4
+ 3rd ay, bytes 4-1
+ ^^^^^^^^^^ Framing offsets
+ */
+ };
+ gsize size = sizeof (data);
+ GVariant *variant = NULL;
+ GVariant *normal_variant = NULL;
+ GVariant *expected = NULL;
+
+ variant = g_variant_new_from_data (data_type, data, size, FALSE, NULL, NULL);
+ g_assert_nonnull (variant);
+
+ g_assert_false (g_variant_is_normal_form (variant));
+
+ normal_variant = g_variant_get_normal_form (variant);
+ g_assert_nonnull (normal_variant);
+ g_assert_cmpuint (g_variant_get_size (normal_variant), <=, size * 3);
+
+ expected = g_variant_new_parsed ("@(ayayiay) ([], [], 0, [])");
+ g_assert_cmpvariant (expected, variant);
+ g_assert_cmpvariant (expected, normal_variant);
+
+ g_variant_unref (expected);
+ g_variant_unref (normal_variant);
+ g_variant_unref (variant);
+}
+
+/* This is a regression test that overlapping entries in the offset table are
+ * decoded consistently, even though theyre non-normal.
+ *
+ * See https://gitlab.gnome.org/GNOME/glib/-/issues/2121#note_910935 */
+static void
+test_normal_checking_tuple_offsets4 (void)
+{
+ /* The expected decoding of this non-normal byte stream is complex. See
+ * section 2.7.3 (Handling Non-Normal Serialised Data) of the GVariant
+ * specification.
+ *
+ * The rule “Child Values Overlapping Framing Offsets” from the specification
+ * says that the first `ay` must be decoded as `[0x01]` even though it
+ * overlaps the first byte of the offset table. However, since commit
+ * 7eedcd76f7d5b8c98fa60013e1fe6e960bf19df3, GLib explicitly doesnt allow
+ * this as its exploitable. So the first `ay` must be given a default value.
+ *
+ * The second `ay` must be given a default value because of rule “End Boundary
+ * Precedes Start Boundary”.
+ *
+ * The third `ay` must be given a default value because its framing offsets
+ * overlap that of the first `ay`.
+ */
+ const GVariantType *data_type = G_VARIANT_TYPE ("(ayayay)");
+ const guint8 data[] = {
+ 0x01, 0x00, 0x02,
+ /*
+ ^──┘
+
+ ^^^^^^^^^^ 1st ay, bytes 0-2 (but given a default value anyway, see above)
+ 2nd ay, bytes 2-0
+ 3rd ay, bytes 0-1
+ ^^^^^^^^^^ Framing offsets
+ */
+ };
+ gsize size = sizeof (data);
+ GVariant *variant = NULL;
+ GVariant *normal_variant = NULL;
+ GVariant *expected = NULL;
+
+ variant = g_variant_new_from_data (data_type, data, size, FALSE, NULL, NULL);
+ g_assert_nonnull (variant);
+
+ g_assert_false (g_variant_is_normal_form (variant));
+
+ normal_variant = g_variant_get_normal_form (variant);
+ g_assert_nonnull (normal_variant);
+ g_assert_cmpuint (g_variant_get_size (normal_variant), <=, size * 3);
+
+ expected = g_variant_new_parsed ("@(ayayay) ([], [], [])");
+ g_assert_cmpvariant (expected, variant);
+ g_assert_cmpvariant (expected, normal_variant);
+
+ g_variant_unref (expected);
+ g_variant_unref (normal_variant);
+ g_variant_unref (variant);
+}
+
/* Test that an empty object path is normalised successfully to the base object
* path, /. */
static void
@@ -5244,6 +5419,12 @@ main (int argc, char **argv)
test_normal_checking_array_offsets2);
g_test_add_func ("/gvariant/normal-checking/tuple-offsets",
test_normal_checking_tuple_offsets);
+ g_test_add_func ("/gvariant/normal-checking/tuple-offsets2",
+ test_normal_checking_tuple_offsets2);
+ g_test_add_func ("/gvariant/normal-checking/tuple-offsets3",
+ test_normal_checking_tuple_offsets3);
+ g_test_add_func ("/gvariant/normal-checking/tuple-offsets4",
+ test_normal_checking_tuple_offsets4);
g_test_add_func ("/gvariant/normal-checking/empty-object-path",
test_normal_checking_empty_object_path);

View file

@ -1,378 +0,0 @@
From a6cb880af0a0932493ba096f01990e694e2c5b72 Mon Sep 17 00:00:00 2001
From: Philip Withnall <pwithnall@endlessos.org>
Date: Tue, 25 Oct 2022 15:14:14 +0100
Subject: [PATCH 08/18] gvariant: Track checked and ordered offsets
independently
The past few commits introduced the concept of known-good offsets in the
offset table (which is used for variable-width arrays and tuples).
Good offsets are ones which are non-overlapping with all the previous
offsets in the table.
If a bad offset is encountered when indexing into the array or tuple,
the cached known-good offset index will not be increased. In this way,
all child variants at and beyond the first bad offset can be returned as
default values rather than dereferencing potentially invalid data.
In this case, there was no information about the fact that the indexes
between the highest known-good index and the requested one had been
checked already. That could lead to a pathological case where an offset
table with an invalid first offset is repeatedly checked in full when
trying to access higher-indexed children.
Avoid that by storing the index of the highest checked offset in the
table, as well as the index of the highest good/ordered offset.
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
Helps: #2121
---
glib/gvariant-core.c | 28 ++++++++++++++++++++++++
glib/gvariant-serialiser.c | 44 +++++++++++++++++++++++++++-----------
glib/gvariant-serialiser.h | 9 ++++++++
glib/gvariant.c | 1 +
glib/tests/gvariant.c | 5 +++++
5 files changed, 75 insertions(+), 12 deletions(-)
--- a/glib/gvariant-core.c
+++ b/glib/gvariant-core.c
@@ -67,6 +67,7 @@ struct _GVariant
GBytes *bytes;
gconstpointer data;
gsize ordered_offsets_up_to;
+ gsize checked_offsets_up_to;
} serialised;
struct
@@ -182,6 +183,24 @@ struct _GVariant
* This field is only relevant for arrays of non
* fixed width types and for tuples.
*
+ * .checked_offsets_up_to: Similarly to .ordered_offsets_up_to, this stores
+ * the index of the highest element, n, whose frame
+ * offsets (and all the preceding frame offsets)
+ * have been checked for validity.
+ *
+ * It is always the case that
+ * .checked_offsets_up_to ≥ .ordered_offsets_up_to.
+ *
+ * If .checked_offsets_up_to == .ordered_offsets_up_to,
+ * then a bad offset has not been found so far.
+ *
+ * If .checked_offsets_up_to > .ordered_offsets_up_to,
+ * then a bad offset has been found at
+ * (.ordered_offsets_up_to + 1).
+ *
+ * This field is only relevant for arrays of non
+ * fixed width types and for tuples.
+ *
* .tree: Only valid when the instance is in tree form.
*
* Note that accesses from other threads could result in
@@ -386,6 +405,7 @@ g_variant_to_serialised (GVariant *value
value->size,
value->depth,
value->contents.serialised.ordered_offsets_up_to,
+ value->contents.serialised.checked_offsets_up_to,
};
return serialised;
}
@@ -418,6 +438,7 @@ g_variant_serialise (GVariant *value,
serialised.data = data;
serialised.depth = value->depth;
serialised.ordered_offsets_up_to = 0;
+ serialised.checked_offsets_up_to = 0;
children = (gpointer *) value->contents.tree.children;
n_children = value->contents.tree.n_children;
@@ -464,10 +485,12 @@ g_variant_fill_gvs (GVariantSerialised *
if (value->state & STATE_SERIALISED)
{
serialised->ordered_offsets_up_to = value->contents.serialised.ordered_offsets_up_to;
+ serialised->checked_offsets_up_to = value->contents.serialised.checked_offsets_up_to;
}
else
{
serialised->ordered_offsets_up_to = 0;
+ serialised->checked_offsets_up_to = 0;
}
if (serialised->data)
@@ -513,6 +536,7 @@ g_variant_ensure_serialised (GVariant *v
value->contents.serialised.data = g_bytes_get_data (bytes, NULL);
value->contents.serialised.bytes = bytes;
value->contents.serialised.ordered_offsets_up_to = G_MAXSIZE;
+ value->contents.serialised.checked_offsets_up_to = G_MAXSIZE;
value->state |= STATE_SERIALISED;
}
}
@@ -594,6 +618,7 @@ g_variant_new_from_bytes (const GVariant
serialised.data = (guchar *) g_bytes_get_data (bytes, &serialised.size);
serialised.depth = 0;
serialised.ordered_offsets_up_to = trusted ? G_MAXSIZE : 0;
+ serialised.checked_offsets_up_to = trusted ? G_MAXSIZE : 0;
if (!g_variant_serialised_check (serialised))
{
@@ -645,6 +670,7 @@ g_variant_new_from_bytes (const GVariant
}
value->contents.serialised.ordered_offsets_up_to = trusted ? G_MAXSIZE : 0;
+ value->contents.serialised.checked_offsets_up_to = trusted ? G_MAXSIZE : 0;
g_clear_pointer (&owned_bytes, g_bytes_unref);
@@ -1142,6 +1168,7 @@ g_variant_get_child_value (GVariant *val
/* Update the cached ordered_offsets_up_to, since @serialised will be thrown away when this function exits */
value->contents.serialised.ordered_offsets_up_to = MAX (value->contents.serialised.ordered_offsets_up_to, serialised.ordered_offsets_up_to);
+ value->contents.serialised.checked_offsets_up_to = MAX (value->contents.serialised.checked_offsets_up_to, serialised.checked_offsets_up_to);
/* Check whether this would cause nesting too deep. If so, return a fake
* child. The only situation we expect this to happen in is with a variant,
@@ -1169,6 +1196,7 @@ g_variant_get_child_value (GVariant *val
g_bytes_ref (value->contents.serialised.bytes);
child->contents.serialised.data = s_child.data;
child->contents.serialised.ordered_offsets_up_to = s_child.ordered_offsets_up_to;
+ child->contents.serialised.checked_offsets_up_to = s_child.checked_offsets_up_to;
return child;
}
--- a/glib/gvariant-serialiser.c
+++ b/glib/gvariant-serialiser.c
@@ -120,6 +120,8 @@
*
* @depth has no restrictions; the depth of a top-level serialized #GVariant is
* zero, and it increases for each level of nested child.
+ *
+ * @checked_offsets_up_to is always ≥ @ordered_offsets_up_to
*/
/* < private >
@@ -147,6 +149,9 @@ g_variant_serialised_check (GVariantSeri
!(serialised.size == 0 || serialised.data != NULL))
return FALSE;
+ if (serialised.ordered_offsets_up_to > serialised.checked_offsets_up_to)
+ return FALSE;
+
/* Depending on the native alignment requirements of the machine, the
* compiler will insert either 3 or 7 padding bytes after the char.
* This will result in the sizeof() the struct being 12 or 16.
@@ -266,6 +271,7 @@ gvs_fixed_sized_maybe_get_child (GVarian
g_variant_type_info_ref (value.type_info);
value.depth++;
value.ordered_offsets_up_to = 0;
+ value.checked_offsets_up_to = 0;
return value;
}
@@ -297,7 +303,7 @@ gvs_fixed_sized_maybe_serialise (GVarian
{
if (n_children)
{
- GVariantSerialised child = { NULL, value.data, value.size, value.depth + 1, 0 };
+ GVariantSerialised child = { NULL, value.data, value.size, value.depth + 1, 0, 0 };
gvs_filler (&child, children[0]);
}
@@ -320,6 +326,7 @@ gvs_fixed_sized_maybe_is_normal (GVarian
value.type_info = g_variant_type_info_element (value.type_info);
value.depth++;
value.ordered_offsets_up_to = 0;
+ value.checked_offsets_up_to = 0;
return g_variant_serialised_is_normal (value);
}
@@ -362,6 +369,7 @@ gvs_variable_sized_maybe_get_child (GVar
value.depth++;
value.ordered_offsets_up_to = 0;
+ value.checked_offsets_up_to = 0;
return value;
}
@@ -392,7 +400,7 @@ gvs_variable_sized_maybe_serialise (GVar
{
if (n_children)
{
- GVariantSerialised child = { NULL, value.data, value.size - 1, value.depth + 1, 0 };
+ GVariantSerialised child = { NULL, value.data, value.size - 1, value.depth + 1, 0, 0 };
/* write the data for the child. */
gvs_filler (&child, children[0]);
@@ -413,6 +421,7 @@ gvs_variable_sized_maybe_is_normal (GVar
value.size--;
value.depth++;
value.ordered_offsets_up_to = 0;
+ value.checked_offsets_up_to = 0;
return g_variant_serialised_is_normal (value);
}
@@ -739,39 +748,46 @@ gvs_variable_sized_array_get_child (GVar
/* If the requested @index_ is beyond the set of indices whose framing offsets
* have been checked, check the remaining offsets to see whether theyre
- * normal (in order, no overlapping array elements). */
- if (index_ > value.ordered_offsets_up_to)
+ * normal (in order, no overlapping array elements).
+ *
+ * Dont bother checking if the highest known-good offset is lower than the
+ * highest checked offset, as that means theres an invalid element at that
+ * index, so theres no need to check further. */
+ if (index_ > value.checked_offsets_up_to &&
+ value.ordered_offsets_up_to == value.checked_offsets_up_to)
{
switch (offsets.offset_size)
{
case 1:
{
value.ordered_offsets_up_to = find_unordered_guint8 (
- offsets.array, value.ordered_offsets_up_to, index_ + 1);
+ offsets.array, value.checked_offsets_up_to, index_ + 1);
break;
}
case 2:
{
value.ordered_offsets_up_to = find_unordered_guint16 (
- offsets.array, value.ordered_offsets_up_to, index_ + 1);
+ offsets.array, value.checked_offsets_up_to, index_ + 1);
break;
}
case 4:
{
value.ordered_offsets_up_to = find_unordered_guint32 (
- offsets.array, value.ordered_offsets_up_to, index_ + 1);
+ offsets.array, value.checked_offsets_up_to, index_ + 1);
break;
}
case 8:
{
value.ordered_offsets_up_to = find_unordered_guint64 (
- offsets.array, value.ordered_offsets_up_to, index_ + 1);
+ offsets.array, value.checked_offsets_up_to, index_ + 1);
break;
}
default:
/* gvs_get_offset_size() only returns maximum 8 */
g_assert_not_reached ();
}
+
+ value.checked_offsets_up_to = index_;
}
if (index_ > value.ordered_offsets_up_to)
@@ -916,6 +932,7 @@ gvs_variable_sized_array_is_normal (GVar
/* All offsets have now been checked. */
value.ordered_offsets_up_to = G_MAXSIZE;
+ value.checked_offsets_up_to = G_MAXSIZE;
return TRUE;
}
@@ -1040,14 +1057,15 @@ gvs_tuple_get_child (GVariantSerialised
* all the tuple *elements* here, not just all the framing offsets, since
* tuples contain a mix of elements which use framing offsets and ones which
* dont. None of them are allowed to overlap. */
- if (index_ > value.ordered_offsets_up_to)
+ if (index_ > value.checked_offsets_up_to &&
+ value.ordered_offsets_up_to == value.checked_offsets_up_to)
{
gsize i, prev_i_end = 0;
- if (value.ordered_offsets_up_to > 0)
- gvs_tuple_get_member_bounds (value, value.ordered_offsets_up_to - 1, offset_size, NULL, &prev_i_end);
+ if (value.checked_offsets_up_to > 0)
+ gvs_tuple_get_member_bounds (value, value.checked_offsets_up_to - 1, offset_size, NULL, &prev_i_end);
- for (i = value.ordered_offsets_up_to; i <= index_; i++)
+ for (i = value.checked_offsets_up_to; i <= index_; i++)
{
gsize i_start, i_end;
@@ -1060,6 +1078,7 @@ gvs_tuple_get_child (GVariantSerialised
}
value.ordered_offsets_up_to = i - 1;
+ value.checked_offsets_up_to = index_;
}
if (index_ > value.ordered_offsets_up_to)
@@ -1257,6 +1276,7 @@ gvs_tuple_is_normal (GVariantSerialised
/* All element bounds have been checked above. */
value.ordered_offsets_up_to = G_MAXSIZE;
+ value.checked_offsets_up_to = G_MAXSIZE;
{
gsize fixed_size;
--- a/glib/gvariant-serialiser.h
+++ b/glib/gvariant-serialiser.h
@@ -41,6 +41,15 @@ typedef struct
* Even when dealing with tuples, @ordered_offsets_up_to is an element index,
* rather than an index into the frame offsets. */
gsize ordered_offsets_up_to;
+
+ /* Similar to @ordered_offsets_up_to. This gives the index of the child element
+ * whose frame offset is the highest in the offset table which has been
+ * checked so far.
+ *
+ * This is always ≥ @ordered_offsets_up_to. It is always an element index.
+ *
+ * See documentation in gvariant-core.c for `struct GVariant` for details. */
+ gsize checked_offsets_up_to;
} GVariantSerialised;
/* deserialization */
--- a/glib/gvariant.c
+++ b/glib/gvariant.c
@@ -5998,6 +5998,7 @@ g_variant_byteswap (GVariant *value)
serialised.data = g_malloc (serialised.size);
serialised.depth = g_variant_get_depth (trusted);
serialised.ordered_offsets_up_to = G_MAXSIZE; /* operating on the normal form */
+ serialised.checked_offsets_up_to = G_MAXSIZE;
g_variant_store (trusted, serialised.data);
g_variant_unref (trusted);
--- a/glib/tests/gvariant.c
+++ b/glib/tests/gvariant.c
@@ -1282,6 +1282,7 @@ random_instance_filler (GVariantSerialis
serialised->depth = 0;
serialised->ordered_offsets_up_to = 0;
+ serialised->checked_offsets_up_to = 0;
g_assert_true (serialised->type_info == instance->type_info);
g_assert_cmpuint (serialised->size, ==, instance->size);
@@ -1449,6 +1450,7 @@ test_maybe (void)
serialised.size = needed_size;
serialised.depth = 0;
serialised.ordered_offsets_up_to = 0;
+ serialised.checked_offsets_up_to = 0;
g_variant_serialiser_serialise (serialised,
random_instance_filler,
@@ -1573,6 +1575,7 @@ test_array (void)
serialised.size = needed_size;
serialised.depth = 0;
serialised.ordered_offsets_up_to = 0;
+ serialised.checked_offsets_up_to = 0;
g_variant_serialiser_serialise (serialised, random_instance_filler,
(gpointer *) instances, n_children);
@@ -1738,6 +1741,7 @@ test_tuple (void)
serialised.size = needed_size;
serialised.depth = 0;
serialised.ordered_offsets_up_to = 0;
+ serialised.checked_offsets_up_to = 0;
g_variant_serialiser_serialise (serialised, random_instance_filler,
(gpointer *) instances, n_children);
@@ -1835,6 +1839,7 @@ test_variant (void)
serialised.size = needed_size;
serialised.depth = 0;
serialised.ordered_offsets_up_to = 0;
+ serialised.checked_offsets_up_to = 0;
g_variant_serialiser_serialise (serialised, random_instance_filler,
(gpointer *) &instance, 1);

View file

@ -1,63 +0,0 @@
From 8c1a7815e7e6695c120cdedff48395c1222af6d1 Mon Sep 17 00:00:00 2001
From: Philip Withnall <withnall@endlessm.com>
Date: Fri, 12 Jun 2020 18:01:13 +0100
Subject: [PATCH 09/18] tests: Add another test for overlapping offsets in
GVariant
Signed-off-by: Philip Withnall <withnall@endlessm.com>
Helps: #2121
---
glib/tests/gvariant.c | 34 ++++++++++++++++++++++++++++++++++
1 file changed, 34 insertions(+)
--- a/glib/tests/gvariant.c
+++ b/glib/tests/gvariant.c
@@ -5019,6 +5019,38 @@ test_recursion_limits_array_in_variant (
g_variant_unref (wrapper_variant);
}
+/* Test that a nested array with invalid values in its offset table (which point
+ * from the inner to the outer array) is normalised successfully without
+ * looping infinitely. */
+static void
+test_normal_checking_array_offsets_overlapped (void)
+{
+ const guint8 data[] = {
+ 0x01, 0x00,
+ };
+ gsize size = sizeof (data);
+ GVariant *variant = NULL;
+ GVariant *normal_variant = NULL;
+ GVariant *expected_variant = NULL;
+
+ variant = g_variant_new_from_data (G_VARIANT_TYPE ("aay"), data, size,
+ FALSE, NULL, NULL);
+ g_assert_nonnull (variant);
+
+ normal_variant = g_variant_get_normal_form (variant);
+ g_assert_nonnull (normal_variant);
+
+ expected_variant = g_variant_new_parsed ("[@ay [], []]");
+ g_assert_cmpvariant (normal_variant, expected_variant);
+
+ g_assert_cmpmem (g_variant_get_data (normal_variant), g_variant_get_size (normal_variant),
+ g_variant_get_data (expected_variant), g_variant_get_size (expected_variant));
+
+ g_variant_unref (expected_variant);
+ g_variant_unref (normal_variant);
+ g_variant_unref (variant);
+}
+
/* Test that an array with invalidly large values in its offset table is
* normalised successfully without looping infinitely. */
static void
@@ -5418,6 +5450,8 @@ main (int argc, char **argv)
g_test_add_func ("/gvariant/normal-checking/tuples",
test_normal_checking_tuples);
+ g_test_add_func ("/gvariant/normal-checking/array-offsets/overlapped",
+ test_normal_checking_array_offsets_overlapped);
g_test_add_func ("/gvariant/normal-checking/array-offsets",
test_normal_checking_array_offsets);
g_test_add_func ("/gvariant/normal-checking/array-offsets2",

View file

@ -1,71 +0,0 @@
From 019505a7ccc32d0afa06e104dc0ac2e63e6f7189 Mon Sep 17 00:00:00 2001
From: Philip Withnall <pwithnall@endlessos.org>
Date: Mon, 24 Oct 2022 16:43:23 +0100
Subject: [PATCH 10/18] tests: Disable some random instance tests of GVariants
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Building a `GVariant` using entirely random data may result in a
non-normally-formed `GVariant`. Its always possible to read these
`GVariant`s, but the API might return default values for some or all of
their components.
In particular, this can easily happen when randomly generating the
offset tables for non-fixed-width container types.
If it does happen, bytewise comparison of the parsed `GVariant` with the
original bytes will not always match. So skip those checks.
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
Helps: #2121
---
glib/tests/gvariant.c | 12 +++++++++---
1 file changed, 9 insertions(+), 3 deletions(-)
--- a/glib/tests/gvariant.c
+++ b/glib/tests/gvariant.c
@@ -1229,6 +1229,7 @@ random_instance_assert (RandomInstance *
GRand *rand;
gsize i;
+ g_assert_true (size == 0 || buffer != NULL);
g_assert_cmpint ((gsize) buffer & ALIGN_BITS & instance->alignment, ==, 0);
g_assert_cmpint (size, ==, instance->size);
@@ -1455,10 +1456,13 @@ test_maybe (void)
g_variant_serialiser_serialise (serialised,
random_instance_filler,
(gpointer *) &instance, 1);
+
child = g_variant_serialised_get_child (serialised, 0);
g_assert_true (child.type_info == instance->type_info);
- random_instance_assert (instance, child.data, child.size);
+ if (child.data != NULL) /* could be NULL if element is non-normal */
+ random_instance_assert (instance, child.data, child.size);
g_variant_type_info_unref (child.type_info);
+
flavoured_free (serialised.data, flavour);
}
}
@@ -1591,7 +1595,8 @@ test_array (void)
child = g_variant_serialised_get_child (serialised, i);
g_assert_true (child.type_info == instances[i]->type_info);
- random_instance_assert (instances[i], child.data, child.size);
+ if (child.data != NULL) /* could be NULL if element is non-normal */
+ random_instance_assert (instances[i], child.data, child.size);
g_variant_type_info_unref (child.type_info);
}
@@ -1757,7 +1762,8 @@ test_tuple (void)
child = g_variant_serialised_get_child (serialised, i);
g_assert_true (child.type_info == instances[i]->type_info);
- random_instance_assert (instances[i], child.data, child.size);
+ if (child.data != NULL) /* could be NULL if element is non-normal */
+ random_instance_assert (instances[i], child.data, child.size);
g_variant_type_info_unref (child.type_info);
}

View file

@ -1,26 +0,0 @@
From 9d2a142807806212a23436d0332b0209733810f2 Mon Sep 17 00:00:00 2001
From: Philip Withnall <pwithnall@endlessos.org>
Date: Mon, 24 Oct 2022 18:14:57 +0100
Subject: [PATCH 11/18] gvariant: Clarify the docs for
g_variant_get_normal_form()
Document how non-normal parts of the `GVariant` are handled.
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
---
glib/gvariant.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
--- a/glib/gvariant.c
+++ b/glib/gvariant.c
@@ -5923,7 +5923,9 @@ g_variant_deep_copy (GVariant *value)
* marked as trusted and a new reference to it is returned.
*
* If @value is found not to be in normal form then a new trusted
- * #GVariant is created with the same value as @value.
+ * #GVariant is created with the same value as @value. The non-normal parts of
+ * @value will be replaced with default values which are guaranteed to be in
+ * normal form.
*
* It makes sense to call this function if you've received #GVariant
* data from untrusted sources and you want to ensure your serialized

View file

@ -1,40 +0,0 @@
From b0ccb1616688290088e49dea2dc0d7fe723136e4 Mon Sep 17 00:00:00 2001
From: Philip Withnall <pwithnall@endlessos.org>
Date: Mon, 24 Oct 2022 18:43:55 +0100
Subject: [PATCH 12/18] gvariant: Port g_variant_deep_copy() to count its
iterations directly
This is equivalent to what `GVariantIter` does, but it means that
`g_variant_deep_copy()` is making its own `g_variant_get_child_value()`
calls.
This will be useful in an upcoming commit, where those child values will
be inspected a little more deeply.
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
Helps: #2121
---
glib/gvariant.c | 7 +++----
1 file changed, 3 insertions(+), 4 deletions(-)
--- a/glib/gvariant.c
+++ b/glib/gvariant.c
@@ -5850,14 +5850,13 @@ g_variant_deep_copy (GVariant *value)
case G_VARIANT_CLASS_VARIANT:
{
GVariantBuilder builder;
- GVariantIter iter;
- GVariant *child;
+ gsize i, n_children;
g_variant_builder_init (&builder, g_variant_get_type (value));
- g_variant_iter_init (&iter, value);
- while ((child = g_variant_iter_next_value (&iter)))
+ for (i = 0, n_children = g_variant_n_children (value); i < n_children; i++)
{
+ GVariant *child = g_variant_get_child_value (value, i);
g_variant_builder_add_value (&builder, g_variant_deep_copy (child));
g_variant_unref (child);
}

View file

@ -1,105 +0,0 @@
Backport of:
From 1770e255ae6cc3f0bf5312322432bbc6524a3632 Mon Sep 17 00:00:00 2001
From: Philip Withnall <pwithnall@endlessos.org>
Date: Tue, 25 Oct 2022 13:03:22 +0100
Subject: [PATCH 13/18] gvariant: Add internal
g_variant_maybe_get_child_value()
This will be used in a following commit.
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
Helps: #2540
---
glib/gvariant-core.c | 68 ++++++++++++++++++++++++++++++++++++++++++++
glib/gvariant-core.h | 3 ++
2 files changed, 71 insertions(+)
--- a/glib/gvariant-core.c
+++ b/glib/gvariant-core.c
@@ -1203,6 +1203,74 @@ g_variant_get_child_value (GVariant *val
}
/**
+ * g_variant_maybe_get_child_value:
+ * @value: a container #GVariant
+ * @index_: the index of the child to fetch
+ *
+ * Reads a child item out of a container #GVariant instance, if it is in normal
+ * form. If it is not in normal form, return %NULL.
+ *
+ * This function behaves the same as g_variant_get_child_value(), except that it
+ * returns %NULL if the child is not in normal form. g_variant_get_child_value()
+ * would instead return a new default value of the correct type.
+ *
+ * This is intended to be used internally to avoid unnecessary #GVariant
+ * allocations.
+ *
+ * The returned value is never floating. You should free it with
+ * g_variant_unref() when you're done with it.
+ *
+ * This function is O(1).
+ *
+ * Returns: (transfer full): the child at the specified index
+ *
+ * Since: 2.72
+ */
+GVariant *
+g_variant_maybe_get_child_value (GVariant *value,
+ gsize index_)
+{
+ g_return_val_if_fail (index_ < g_variant_n_children (value), NULL);
+ g_return_val_if_fail (value->depth < G_MAXSIZE, NULL);
+
+ if (~g_atomic_int_get (&value->state) & STATE_SERIALISED)
+ {
+ g_variant_lock (value);
+
+ if (~value->state & STATE_SERIALISED)
+ {
+ GVariant *child;
+
+ child = g_variant_ref (value->contents.tree.children[index_]);
+ g_variant_unlock (value);
+
+ return child;
+ }
+
+ g_variant_unlock (value);
+ }
+
+ {
+ GVariantSerialised serialised = g_variant_to_serialised (value);
+ GVariantSerialised s_child;
+
+ /* get the serializer to extract the serialized data for the child
+ * from the serialized data for the container
+ */
+ s_child = g_variant_serialised_get_child (serialised, index_);
+
+ if (!(value->state & STATE_TRUSTED) && s_child.data == NULL)
+ {
+ g_variant_type_info_unref (s_child.type_info);
+ return NULL;
+ }
+
+ g_variant_type_info_unref (s_child.type_info);
+ return g_variant_get_child_value (value, index_);
+ }
+}
+
+/**
* g_variant_store:
* @value: the #GVariant to store
* @data: (not nullable): the location to store the serialized data at
--- a/glib/gvariant-core.h
+++ b/glib/gvariant-core.h
@@ -36,4 +36,7 @@ GVariantTypeInfo * g_variant_get_ty
gsize g_variant_get_depth (GVariant *value);
+GVariant * g_variant_maybe_get_child_value (GVariant *value,
+ gsize index_);
+
#endif /* __G_VARIANT_CORE_H__ */

View file

@ -1,125 +0,0 @@
From 82fc15af4c84a2645343c51b18ab3528c51790ab Mon Sep 17 00:00:00 2001
From: Philip Withnall <pwithnall@endlessos.org>
Date: Tue, 25 Oct 2022 13:03:45 +0100
Subject: [PATCH 14/18] gvariant: Cut allocs of default values for children of
non-normal arrays
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
This improves a slow case in `g_variant_get_normal_form()` where
allocating many identical default values for the children of a
variable-sized array which has a malformed offset table would take a lot
of time.
The fix is to make all child values after the first invalid one be
references to the default value emitted for the first invalid one,
rather than identical new `GVariant`s.
In particular, this fixes a case where an attacker could create an array
of length L of very large tuples of size T each, corrupt the offset table
so they dont have to specify the array content, and then induce
`g_variant_get_normal_form()` into allocating L×T default values from an
input which is significantly smaller than L×T in length.
A pre-existing workaround for this issue is for code to call
`g_variant_is_normal_form()` before calling
`g_variant_get_normal_form()`, and to skip the latter call if the former
returns false. This commit improves the behaviour in the case that
`g_variant_get_normal_form()` is called anyway.
This fix changes the time to run the `fuzz_variant_binary` test on the
testcase from oss-fuzz#19777 from >60s (before being terminated) with
2.3GB of memory usage and 580k page faults; to 32s, 8.3MB of memory
usage and 1500 page faults (as measured by `time -v`).
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
Fixes: #2540
oss-fuzz#19777
---
glib/gvariant.c | 66 ++++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 65 insertions(+), 1 deletion(-)
--- a/glib/gvariant.c
+++ b/glib/gvariant.c
@@ -5844,7 +5844,6 @@ g_variant_deep_copy (GVariant *value)
switch (g_variant_classify (value))
{
case G_VARIANT_CLASS_MAYBE:
- case G_VARIANT_CLASS_ARRAY:
case G_VARIANT_CLASS_TUPLE:
case G_VARIANT_CLASS_DICT_ENTRY:
case G_VARIANT_CLASS_VARIANT:
@@ -5863,6 +5862,71 @@ g_variant_deep_copy (GVariant *value)
return g_variant_builder_end (&builder);
}
+
+ case G_VARIANT_CLASS_ARRAY:
+ {
+ GVariantBuilder builder;
+ gsize i, n_children;
+ GVariant *first_invalid_child_deep_copy = NULL;
+
+ /* Arrays are in theory treated the same as maybes, tuples, dict entries
+ * and variants, and could be another case in the above block of code.
+ *
+ * However, they have the property that when dealing with non-normal
+ * data (which is the only time g_variant_deep_copy() is currently
+ * called) in a variable-sized array, the code above can easily end up
+ * creating many default child values in order to return an array which
+ * is of the right length and type, but without containing non-normal
+ * data. This can happen if the offset table for the array is malformed.
+ *
+ * In this case, the code above would end up allocating the same default
+ * value for each one of the child indexes beyond the first malformed
+ * entry in the offset table. This can end up being a lot of identical
+ * allocations of default values, particularly if the non-normal array
+ * is crafted maliciously.
+ *
+ * Avoid that problem by returning a new reference to the same default
+ * value for every child after the first invalid one. This results in
+ * returning an equivalent array, in normal form and trusted — but with
+ * significantly fewer memory allocations.
+ *
+ * See https://gitlab.gnome.org/GNOME/glib/-/issues/2540 */
+
+ g_variant_builder_init (&builder, g_variant_get_type (value));
+
+ for (i = 0, n_children = g_variant_n_children (value); i < n_children; i++)
+ {
+ /* Try maybe_get_child_value() first; if it returns NULL, this child
+ * is non-normal. get_child_value() would have constructed and
+ * returned a default value in that case. */
+ GVariant *child = g_variant_maybe_get_child_value (value, i);
+
+ if (child != NULL)
+ {
+ /* Non-normal children may not always be contiguous, as they may
+ * be non-normal for reasons other than invalid offset table
+ * entries. As they are all the same type, they will all have
+ * the same default value though, so keep that around. */
+ g_variant_builder_add_value (&builder, g_variant_deep_copy (child));
+ }
+ else if (child == NULL && first_invalid_child_deep_copy != NULL)
+ {
+ g_variant_builder_add_value (&builder, first_invalid_child_deep_copy);
+ }
+ else if (child == NULL)
+ {
+ child = g_variant_get_child_value (value, i);
+ first_invalid_child_deep_copy = g_variant_ref_sink (g_variant_deep_copy (child));
+ g_variant_builder_add_value (&builder, first_invalid_child_deep_copy);
+ }
+
+ g_clear_pointer (&child, g_variant_unref);
+ }
+
+ g_clear_pointer (&first_invalid_child_deep_copy, g_variant_unref);
+
+ return g_variant_builder_end (&builder);
+ }
case G_VARIANT_CLASS_BOOLEAN:
return g_variant_new_boolean (g_variant_get_boolean (value));

View file

@ -1,21 +0,0 @@
From 935f1c200789c76ad5b51b1f403f611e3cc75318 Mon Sep 17 00:00:00 2001
From: Philip Withnall <pwithnall@endlessos.org>
Date: Tue, 25 Oct 2022 18:03:56 +0100
Subject: [PATCH 15/18] gvariant: Fix a leak of a GVariantTypeInfo on an error
handling path
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
---
glib/gvariant-core.c | 1 +
1 file changed, 1 insertion(+)
--- a/glib/gvariant-core.c
+++ b/glib/gvariant-core.c
@@ -1181,6 +1181,7 @@ g_variant_get_child_value (GVariant *val
G_VARIANT_MAX_RECURSION_DEPTH - value->depth)
{
g_assert (g_variant_is_of_type (value, G_VARIANT_TYPE_VARIANT));
+ g_variant_type_info_unref (s_child.type_info);
return g_variant_new_tuple (NULL, 0);
}

View file

@ -1,280 +0,0 @@
From f1dfc5d0c5c0486b5fccb2ceddf1db1162c7033c Mon Sep 17 00:00:00 2001
From: Philip Withnall <pwithnall@endlessos.org>
Date: Thu, 27 Oct 2022 12:00:04 +0100
Subject: [PATCH 16/18] gvariant-serialiser: Check offset table entry size is
minimal
The entries in an offset table (which is used for variable sized arrays
and tuples containing variable sized members) are sized so that they can
address every byte in the overall variant.
The specification requires that for a variant to be in normal form, its
offset table entries must be the minimum width such that they can
address every byte in the variant.
That minimality requirement was not checked in
`g_variant_is_normal_form()`, leading to two different byte arrays being
interpreted as the normal form of a given variant tree. That kind of
confusion could potentially be exploited, and is certainly a bug.
Fix it by adding the necessary checks on offset table entry width, and
unit tests.
Spotted by William Manley.
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
Fixes: #2794
---
glib/gvariant-serialiser.c | 19 +++-
glib/tests/gvariant.c | 176 +++++++++++++++++++++++++++++++++++++
2 files changed, 194 insertions(+), 1 deletion(-)
--- a/glib/gvariant-serialiser.c
+++ b/glib/gvariant-serialiser.c
@@ -694,6 +694,10 @@ gvs_variable_sized_array_get_frame_offse
out.data_size = last_end;
out.array = value.data + last_end;
out.length = offsets_array_size / out.offset_size;
+
+ if (out.length > 0 && gvs_calculate_total_size (last_end, out.length) != value.size)
+ return out; /* offset size not minimal */
+
out.is_normal = TRUE;
return out;
@@ -1201,6 +1205,7 @@ gvs_tuple_is_normal (GVariantSerialised
gsize length;
gsize offset;
gsize i;
+ gsize offset_table_size;
/* as per the comment in gvs_tuple_get_child() */
if G_UNLIKELY (value.data == NULL && value.size != 0)
@@ -1305,7 +1310,19 @@ gvs_tuple_is_normal (GVariantSerialised
}
}
- return offset_ptr == offset;
+ /* @offset_ptr has been counting backwards from the end of the variant, to
+ * find the beginning of the offset table. @offset has been counting forwards
+ * from the beginning of the variant to find the end of the data. They should
+ * have met in the middle. */
+ if (offset_ptr != offset)
+ return FALSE;
+
+ offset_table_size = value.size - offset_ptr;
+ if (value.size > 0 &&
+ gvs_calculate_total_size (offset, offset_table_size / offset_size) != value.size)
+ return FALSE; /* offset size not minimal */
+
+ return TRUE;
}
/* Variants {{{2
--- a/glib/tests/gvariant.c
+++ b/glib/tests/gvariant.c
@@ -5122,6 +5122,86 @@ test_normal_checking_array_offsets2 (voi
g_variant_unref (variant);
}
+/* Test that an otherwise-valid serialised GVariant is considered non-normal if
+ * its offset table entries are too wide.
+ *
+ * See §2.3.6 (Framing Offsets) of the GVariant specification. */
+static void
+test_normal_checking_array_offsets_minimal_sized (void)
+{
+ GVariantBuilder builder;
+ gsize i;
+ GVariant *aay_constructed = NULL;
+ const guint8 *data = NULL;
+ guint8 *data_owned = NULL;
+ GVariant *aay_deserialised = NULL;
+ GVariant *aay_normalised = NULL;
+
+ /* Construct an array of type aay, consisting of 128 elements which are each
+ * an empty array, i.e. `[[] * 128]`. This is chosen because the inner
+ * elements are variable sized (making the outer array variable sized, so it
+ * must have an offset table), but they are also zero-sized when serialised.
+ * So the serialised representation of @aay_constructed consists entirely of
+ * its offset table, which is entirely zeroes.
+ *
+ * The array is chosen to be 128 elements long because that means offset
+ * table entries which are 1 byte long. If the elements in the array were
+ * non-zero-sized (to the extent that the overall array is ≥256 bytes long),
+ * the offset table entries would end up being 2 bytes long. */
+ g_variant_builder_init (&builder, G_VARIANT_TYPE ("aay"));
+
+ for (i = 0; i < 128; i++)
+ g_variant_builder_add_value (&builder, g_variant_new_array (G_VARIANT_TYPE_BYTE, NULL, 0));
+
+ aay_constructed = g_variant_builder_end (&builder);
+
+ /* Verify that the constructed array is in normal form, and its serialised
+ * form is `b'\0' * 128`. */
+ g_assert_true (g_variant_is_normal_form (aay_constructed));
+ g_assert_cmpuint (g_variant_n_children (aay_constructed), ==, 128);
+ g_assert_cmpuint (g_variant_get_size (aay_constructed), ==, 128);
+
+ data = g_variant_get_data (aay_constructed);
+ for (i = 0; i < g_variant_get_size (aay_constructed); i++)
+ g_assert_cmpuint (data[i], ==, 0);
+
+ /* Construct a serialised `aay` GVariant which is `b'\0' * 256`. This has to
+ * be a non-normal form of `[[] * 128]`, with 2-byte-long offset table
+ * entries, because each offset table entry has to be able to reference all of
+ * the byte boundaries in the container. All the entries in the offset table
+ * are zero, so all the elements of the array are zero-sized. */
+ data = data_owned = g_malloc0 (256);
+ aay_deserialised = g_variant_new_from_data (G_VARIANT_TYPE ("aay"),
+ data,
+ 256,
+ FALSE,
+ g_free,
+ g_steal_pointer (&data_owned));
+
+ g_assert_false (g_variant_is_normal_form (aay_deserialised));
+ g_assert_cmpuint (g_variant_n_children (aay_deserialised), ==, 128);
+ g_assert_cmpuint (g_variant_get_size (aay_deserialised), ==, 256);
+
+ data = g_variant_get_data (aay_deserialised);
+ for (i = 0; i < g_variant_get_size (aay_deserialised); i++)
+ g_assert_cmpuint (data[i], ==, 0);
+
+ /* Get its normal form. That should change the serialised size. */
+ aay_normalised = g_variant_get_normal_form (aay_deserialised);
+
+ g_assert_true (g_variant_is_normal_form (aay_normalised));
+ g_assert_cmpuint (g_variant_n_children (aay_normalised), ==, 128);
+ g_assert_cmpuint (g_variant_get_size (aay_normalised), ==, 128);
+
+ data = g_variant_get_data (aay_normalised);
+ for (i = 0; i < g_variant_get_size (aay_normalised); i++)
+ g_assert_cmpuint (data[i], ==, 0);
+
+ g_variant_unref (aay_normalised);
+ g_variant_unref (aay_deserialised);
+ g_variant_unref (aay_constructed);
+}
+
/* Test that a tuple with invalidly large values in its offset table is
* normalised successfully without looping infinitely. */
static void
@@ -5316,6 +5396,98 @@ test_normal_checking_tuple_offsets4 (voi
g_variant_unref (variant);
}
+/* Test that an otherwise-valid serialised GVariant is considered non-normal if
+ * its offset table entries are too wide.
+ *
+ * See §2.3.6 (Framing Offsets) of the GVariant specification. */
+static void
+test_normal_checking_tuple_offsets_minimal_sized (void)
+{
+ GString *type_string = NULL;
+ GVariantBuilder builder;
+ gsize i;
+ GVariant *ray_constructed = NULL;
+ const guint8 *data = NULL;
+ guint8 *data_owned = NULL;
+ GVariant *ray_deserialised = NULL;
+ GVariant *ray_normalised = NULL;
+
+ /* Construct a tuple of type (ay…ay), consisting of 129 members which are each
+ * an empty array, i.e. `([] * 129)`. This is chosen because the inner
+ * members are variable sized, so the outer tuple must have an offset table,
+ * but they are also zero-sized when serialised. So the serialised
+ * representation of @ray_constructed consists entirely of its offset table,
+ * which is entirely zeroes.
+ *
+ * The tuple is chosen to be 129 members long because that means it has 128
+ * offset table entries which are 1 byte long each. If the members in the
+ * tuple were non-zero-sized (to the extent that the overall tuple is ≥256
+ * bytes long), the offset table entries would end up being 2 bytes long.
+ *
+ * 129 members are used unlike 128 array elements in
+ * test_normal_checking_array_offsets_minimal_sized(), because the last member
+ * in a tuple never needs an offset table entry. */
+ type_string = g_string_new ("");
+ g_string_append_c (type_string, '(');
+ for (i = 0; i < 129; i++)
+ g_string_append (type_string, "ay");
+ g_string_append_c (type_string, ')');
+
+ g_variant_builder_init (&builder, G_VARIANT_TYPE (type_string->str));
+
+ for (i = 0; i < 129; i++)
+ g_variant_builder_add_value (&builder, g_variant_new_array (G_VARIANT_TYPE_BYTE, NULL, 0));
+
+ ray_constructed = g_variant_builder_end (&builder);
+
+ /* Verify that the constructed tuple is in normal form, and its serialised
+ * form is `b'\0' * 128`. */
+ g_assert_true (g_variant_is_normal_form (ray_constructed));
+ g_assert_cmpuint (g_variant_n_children (ray_constructed), ==, 129);
+ g_assert_cmpuint (g_variant_get_size (ray_constructed), ==, 128);
+
+ data = g_variant_get_data (ray_constructed);
+ for (i = 0; i < g_variant_get_size (ray_constructed); i++)
+ g_assert_cmpuint (data[i], ==, 0);
+
+ /* Construct a serialised `(ay…ay)` GVariant which is `b'\0' * 256`. This has
+ * to be a non-normal form of `([] * 129)`, with 2-byte-long offset table
+ * entries, because each offset table entry has to be able to reference all of
+ * the byte boundaries in the container. All the entries in the offset table
+ * are zero, so all the members of the tuple are zero-sized. */
+ data = data_owned = g_malloc0 (256);
+ ray_deserialised = g_variant_new_from_data (G_VARIANT_TYPE (type_string->str),
+ data,
+ 256,
+ FALSE,
+ g_free,
+ g_steal_pointer (&data_owned));
+
+ g_assert_false (g_variant_is_normal_form (ray_deserialised));
+ g_assert_cmpuint (g_variant_n_children (ray_deserialised), ==, 129);
+ g_assert_cmpuint (g_variant_get_size (ray_deserialised), ==, 256);
+
+ data = g_variant_get_data (ray_deserialised);
+ for (i = 0; i < g_variant_get_size (ray_deserialised); i++)
+ g_assert_cmpuint (data[i], ==, 0);
+
+ /* Get its normal form. That should change the serialised size. */
+ ray_normalised = g_variant_get_normal_form (ray_deserialised);
+
+ g_assert_true (g_variant_is_normal_form (ray_normalised));
+ g_assert_cmpuint (g_variant_n_children (ray_normalised), ==, 129);
+ g_assert_cmpuint (g_variant_get_size (ray_normalised), ==, 128);
+
+ data = g_variant_get_data (ray_normalised);
+ for (i = 0; i < g_variant_get_size (ray_normalised); i++)
+ g_assert_cmpuint (data[i], ==, 0);
+
+ g_variant_unref (ray_normalised);
+ g_variant_unref (ray_deserialised);
+ g_variant_unref (ray_constructed);
+ g_string_free (type_string, TRUE);
+}
+
/* Test that an empty object path is normalised successfully to the base object
* path, /. */
static void
@@ -5462,6 +5634,8 @@ main (int argc, char **argv)
test_normal_checking_array_offsets);
g_test_add_func ("/gvariant/normal-checking/array-offsets2",
test_normal_checking_array_offsets2);
+ g_test_add_func ("/gvariant/normal-checking/array-offsets/minimal-sized",
+ test_normal_checking_array_offsets_minimal_sized);
g_test_add_func ("/gvariant/normal-checking/tuple-offsets",
test_normal_checking_tuple_offsets);
g_test_add_func ("/gvariant/normal-checking/tuple-offsets2",
@@ -5470,6 +5644,8 @@ main (int argc, char **argv)
test_normal_checking_tuple_offsets3);
g_test_add_func ("/gvariant/normal-checking/tuple-offsets4",
test_normal_checking_tuple_offsets4);
+ g_test_add_func ("/gvariant/normal-checking/tuple-offsets/minimal-sized",
+ test_normal_checking_tuple_offsets_minimal_sized);
g_test_add_func ("/gvariant/normal-checking/empty-object-path",
test_normal_checking_empty_object_path);

View file

@ -1,89 +0,0 @@
From 781f05a22ef11d8a2177b4e9078978decec36dd0 Mon Sep 17 00:00:00 2001
From: Philip Withnall <pwithnall@endlessos.org>
Date: Thu, 27 Oct 2022 16:13:54 +0100
Subject: [PATCH 17/18] gvariant: Fix g_variant_byteswap() returning non-normal
data sometimes
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
If `g_variant_byteswap()` was called on a non-normal variant of a type
which doesnt need byteswapping, it would return a non-normal output.
That contradicts the documentation, which says that the return value is
always in normal form.
Fix the code so it matches the documentation.
Includes a unit test.
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
Helps: #2797
---
glib/gvariant.c | 8 +++++---
glib/tests/gvariant.c | 24 ++++++++++++++++++++++++
2 files changed, 29 insertions(+), 3 deletions(-)
--- a/glib/gvariant.c
+++ b/glib/gvariant.c
@@ -6070,14 +6070,16 @@ g_variant_byteswap (GVariant *value)
g_variant_serialised_byteswap (serialised);
bytes = g_bytes_new_take (serialised.data, serialised.size);
- new = g_variant_new_from_bytes (g_variant_get_type (value), bytes, TRUE);
+ new = g_variant_ref_sink (g_variant_new_from_bytes (g_variant_get_type (value), bytes, TRUE));
g_bytes_unref (bytes);
}
else
/* contains no multi-byte data */
- new = value;
+ new = g_variant_get_normal_form (value);
- return g_variant_ref_sink (new);
+ g_assert (g_variant_is_trusted (new));
+
+ return g_steal_pointer (&new);
}
/**
--- a/glib/tests/gvariant.c
+++ b/glib/tests/gvariant.c
@@ -3833,6 +3833,29 @@ test_gv_byteswap (void)
}
static void
+test_gv_byteswap_non_normal_non_aligned (void)
+{
+ const guint8 data[] = { 0x02 };
+ GVariant *v = NULL;
+ GVariant *v_byteswapped = NULL;
+
+ g_test_summary ("Test that calling g_variant_byteswap() on a variant which "
+ "is in non-normal form and doesnt need byteswapping returns "
+ "the same variant in normal form.");
+
+ v = g_variant_new_from_data (G_VARIANT_TYPE_BOOLEAN, data, sizeof (data), FALSE, NULL, NULL);
+ g_assert_false (g_variant_is_normal_form (v));
+
+ v_byteswapped = g_variant_byteswap (v);
+ g_assert_true (g_variant_is_normal_form (v_byteswapped));
+
+ g_assert_cmpvariant (v, v_byteswapped);
+
+ g_variant_unref (v);
+ g_variant_unref (v_byteswapped);
+}
+
+static void
test_parser (void)
{
TreeInstance *tree;
@@ -5599,6 +5622,7 @@ main (int argc, char **argv)
g_test_add_func ("/gvariant/builder-memory", test_builder_memory);
g_test_add_func ("/gvariant/hashing", test_hashing);
g_test_add_func ("/gvariant/byteswap", test_gv_byteswap);
+ g_test_add_func ("/gvariant/byteswap/non-normal-non-aligned", test_gv_byteswap_non_normal_non_aligned);
g_test_add_func ("/gvariant/parser", test_parses);
g_test_add_func ("/gvariant/parser/integer-bounds", test_parser_integer_bounds);
g_test_add_func ("/gvariant/parser/recursion", test_parser_recursion);

View file

@ -1,290 +0,0 @@
From 7d7efce1d9c379fdd7d2ff58caea88f8806fdd2e Mon Sep 17 00:00:00 2001
From: Philip Withnall <pwithnall@endlessos.org>
Date: Thu, 27 Oct 2022 22:53:13 +0100
Subject: [PATCH 18/18] gvariant: Allow g_variant_byteswap() to operate on
tree-form variants
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
This avoids needing to always serialise a variant before byteswapping it.
With variants in non-normal forms, serialisation can result in a large
increase in size of the variant, and a lot of allocations for leaf
`GVariant`s. This can lead to a denial of service attack.
Avoid that by changing byteswapping so that it happens on the tree form
of the variant if the input is in non-normal form. If the input is in
normal form (either serialised or in tree form), continue using the
existing code as byteswapping an already-serialised normal variant is
about 3× faster than byteswapping on the equivalent tree form.
The existing unit tests cover byteswapping well, but need some
adaptation so that they operate on tree form variants too.
I considered dropping the serialised byteswapping code and doing all
byteswapping on tree-form variants, as that would make maintenance
simpler (avoiding having two parallel implementations of byteswapping).
However, most inputs to `g_variant_byteswap()` are likely to be
serialised variants (coming from a byte array of input from some foreign
source) and most of them are going to be in normal form (as corruption
and malicious action are rare). So getting rid of the serialised
byteswapping code would impose quite a performance penalty on the common
case.
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
Fixes: #2797
---
glib/gvariant.c | 87 ++++++++++++++++++++++++++++++++-----------
glib/tests/gvariant.c | 57 ++++++++++++++++++++++++----
2 files changed, 115 insertions(+), 29 deletions(-)
--- a/glib/gvariant.c
+++ b/glib/gvariant.c
@@ -5839,7 +5839,8 @@ g_variant_iter_loop (GVariantIter *iter,
/* Serialized data {{{1 */
static GVariant *
-g_variant_deep_copy (GVariant *value)
+g_variant_deep_copy (GVariant *value,
+ gboolean byteswap)
{
switch (g_variant_classify (value))
{
@@ -5856,7 +5857,7 @@ g_variant_deep_copy (GVariant *value)
for (i = 0, n_children = g_variant_n_children (value); i < n_children; i++)
{
GVariant *child = g_variant_get_child_value (value, i);
- g_variant_builder_add_value (&builder, g_variant_deep_copy (child));
+ g_variant_builder_add_value (&builder, g_variant_deep_copy (child, byteswap));
g_variant_unref (child);
}
@@ -5907,7 +5908,7 @@ g_variant_deep_copy (GVariant *value)
* be non-normal for reasons other than invalid offset table
* entries. As they are all the same type, they will all have
* the same default value though, so keep that around. */
- g_variant_builder_add_value (&builder, g_variant_deep_copy (child));
+ g_variant_builder_add_value (&builder, g_variant_deep_copy (child, byteswap));
}
else if (child == NULL && first_invalid_child_deep_copy != NULL)
{
@@ -5916,7 +5917,7 @@ g_variant_deep_copy (GVariant *value)
else if (child == NULL)
{
child = g_variant_get_child_value (value, i);
- first_invalid_child_deep_copy = g_variant_ref_sink (g_variant_deep_copy (child));
+ first_invalid_child_deep_copy = g_variant_ref_sink (g_variant_deep_copy (child, byteswap));
g_variant_builder_add_value (&builder, first_invalid_child_deep_copy);
}
@@ -5935,28 +5936,63 @@ g_variant_deep_copy (GVariant *value)
return g_variant_new_byte (g_variant_get_byte (value));
case G_VARIANT_CLASS_INT16:
- return g_variant_new_int16 (g_variant_get_int16 (value));
+ if (byteswap)
+ return g_variant_new_int16 (GUINT16_SWAP_LE_BE (g_variant_get_int16 (value)));
+ else
+ return g_variant_new_int16 (g_variant_get_int16 (value));
case G_VARIANT_CLASS_UINT16:
- return g_variant_new_uint16 (g_variant_get_uint16 (value));
+ if (byteswap)
+ return g_variant_new_uint16 (GUINT16_SWAP_LE_BE (g_variant_get_uint16 (value)));
+ else
+ return g_variant_new_uint16 (g_variant_get_uint16 (value));
case G_VARIANT_CLASS_INT32:
- return g_variant_new_int32 (g_variant_get_int32 (value));
+ if (byteswap)
+ return g_variant_new_int32 (GUINT32_SWAP_LE_BE (g_variant_get_int32 (value)));
+ else
+ return g_variant_new_int32 (g_variant_get_int32 (value));
case G_VARIANT_CLASS_UINT32:
- return g_variant_new_uint32 (g_variant_get_uint32 (value));
+ if (byteswap)
+ return g_variant_new_uint32 (GUINT32_SWAP_LE_BE (g_variant_get_uint32 (value)));
+ else
+ return g_variant_new_uint32 (g_variant_get_uint32 (value));
case G_VARIANT_CLASS_INT64:
- return g_variant_new_int64 (g_variant_get_int64 (value));
+ if (byteswap)
+ return g_variant_new_int64 (GUINT64_SWAP_LE_BE (g_variant_get_int64 (value)));
+ else
+ return g_variant_new_int64 (g_variant_get_int64 (value));
case G_VARIANT_CLASS_UINT64:
- return g_variant_new_uint64 (g_variant_get_uint64 (value));
+ if (byteswap)
+ return g_variant_new_uint64 (GUINT64_SWAP_LE_BE (g_variant_get_uint64 (value)));
+ else
+ return g_variant_new_uint64 (g_variant_get_uint64 (value));
case G_VARIANT_CLASS_HANDLE:
- return g_variant_new_handle (g_variant_get_handle (value));
+ if (byteswap)
+ return g_variant_new_handle (GUINT32_SWAP_LE_BE (g_variant_get_handle (value)));
+ else
+ return g_variant_new_handle (g_variant_get_handle (value));
case G_VARIANT_CLASS_DOUBLE:
- return g_variant_new_double (g_variant_get_double (value));
+ if (byteswap)
+ {
+ /* We have to convert the double to a uint64 here using a union,
+ * because a cast will round it numerically. */
+ union
+ {
+ guint64 u64;
+ gdouble dbl;
+ } u1, u2;
+ u1.dbl = g_variant_get_double (value);
+ u2.u64 = GUINT64_SWAP_LE_BE (u1.u64);
+ return g_variant_new_double (u2.dbl);
+ }
+ else
+ return g_variant_new_double (g_variant_get_double (value));
case G_VARIANT_CLASS_STRING:
return g_variant_new_string (g_variant_get_string (value, NULL));
@@ -6013,7 +6049,7 @@ g_variant_get_normal_form (GVariant *val
if (g_variant_is_normal_form (value))
return g_variant_ref (value);
- trusted = g_variant_deep_copy (value);
+ trusted = g_variant_deep_copy (value, FALSE);
g_assert (g_variant_is_trusted (trusted));
return g_variant_ref_sink (trusted);
@@ -6033,6 +6069,11 @@ g_variant_get_normal_form (GVariant *val
* contain multi-byte numeric data. That include strings, booleans,
* bytes and containers containing only these things (recursively).
*
+ * While this function can safely handle untrusted, non-normal data, it is
+ * recommended to check whether the input is in normal form beforehand, using
+ * g_variant_is_normal_form(), and to reject non-normal inputs if your
+ * application can be strict about what inputs it rejects.
+ *
* The returned value is always in normal form and is marked as trusted.
*
* Returns: (transfer full): the byteswapped form of @value
@@ -6050,22 +6091,21 @@ g_variant_byteswap (GVariant *value)
g_variant_type_info_query (type_info, &alignment, NULL);
- if (alignment)
- /* (potentially) contains multi-byte numeric data */
+ if (alignment && g_variant_is_normal_form (value))
{
+ /* (potentially) contains multi-byte numeric data, but is also already in
+ * normal form so we can use a faster byteswapping codepath on the
+ * serialised data */
GVariantSerialised serialised = { 0, };
- GVariant *trusted;
GBytes *bytes;
- trusted = g_variant_get_normal_form (value);
- serialised.type_info = g_variant_get_type_info (trusted);
- serialised.size = g_variant_get_size (trusted);
+ serialised.type_info = g_variant_get_type_info (value);
+ serialised.size = g_variant_get_size (value);
serialised.data = g_malloc (serialised.size);
- serialised.depth = g_variant_get_depth (trusted);
+ serialised.depth = g_variant_get_depth (value);
serialised.ordered_offsets_up_to = G_MAXSIZE; /* operating on the normal form */
serialised.checked_offsets_up_to = G_MAXSIZE;
- g_variant_store (trusted, serialised.data);
- g_variant_unref (trusted);
+ g_variant_store (value, serialised.data);
g_variant_serialised_byteswap (serialised);
@@ -6073,6 +6113,9 @@ g_variant_byteswap (GVariant *value)
new = g_variant_ref_sink (g_variant_new_from_bytes (g_variant_get_type (value), bytes, TRUE));
g_bytes_unref (bytes);
}
+ else if (alignment)
+ /* (potentially) contains multi-byte numeric data */
+ new = g_variant_ref_sink (g_variant_deep_copy (value, TRUE));
else
/* contains no multi-byte data */
new = g_variant_get_normal_form (value);
--- a/glib/tests/gvariant.c
+++ b/glib/tests/gvariant.c
@@ -2286,24 +2286,67 @@ serialise_tree (TreeInstance *tree
static void
test_byteswap (void)
{
- GVariantSerialised one = { 0, }, two = { 0, };
+ GVariantSerialised one = { 0, }, two = { 0, }, three = { 0, };
TreeInstance *tree;
+ GVariant *one_variant = NULL;
+ GVariant *two_variant = NULL;
+ GVariant *two_byteswapped = NULL;
+ GVariant *three_variant = NULL;
+ GVariant *three_byteswapped = NULL;
+ guint8 *three_data_copy = NULL;
+ gsize three_size_copy = 0;
+ /* Write a tree out twice, once normally and once byteswapped. */
tree = tree_instance_new (NULL, 3);
serialise_tree (tree, &one);
+ one_variant = g_variant_new_from_data (G_VARIANT_TYPE (g_variant_type_info_get_type_string (one.type_info)),
+ one.data, one.size, FALSE, NULL, NULL);
+
i_am_writing_byteswapped = TRUE;
serialise_tree (tree, &two);
+ serialise_tree (tree, &three);
i_am_writing_byteswapped = FALSE;
- g_variant_serialised_byteswap (two);
-
- g_assert_cmpmem (one.data, one.size, two.data, two.size);
- g_assert_cmpuint (one.depth, ==, two.depth);
-
+ /* Swap the first byteswapped one back using the function we want to test. */
+ two_variant = g_variant_new_from_data (G_VARIANT_TYPE (g_variant_type_info_get_type_string (two.type_info)),
+ two.data, two.size, FALSE, NULL, NULL);
+ two_byteswapped = g_variant_byteswap (two_variant);
+
+ /* Make the second byteswapped one non-normal (hopefully), and then byteswap
+ * it back using the function we want to test in its non-normal mode.
+ * This might not work because its not necessarily possible to make an
+ * arbitrary random variant non-normal. Adding a single zero byte to the end
+ * often makes something non-normal but still readable. */
+ three_size_copy = three.size + 1;
+ three_data_copy = g_malloc (three_size_copy);
+ memcpy (three_data_copy, three.data, three.size);
+ three_data_copy[three.size] = '\0';
+
+ three_variant = g_variant_new_from_data (G_VARIANT_TYPE (g_variant_type_info_get_type_string (three.type_info)),
+ three_data_copy, three_size_copy, FALSE, NULL, NULL);
+ three_byteswapped = g_variant_byteswap (three_variant);
+
+ /* Check theyre the same. We can always compare @one_variant and
+ * @two_byteswapped. We can only compare @two_byteswapped and
+ * @three_byteswapped if @two_variant and @three_variant are equal: in that
+ * case, the corruption to @three_variant was enough to make it non-normal but
+ * not enough to change its value. */
+ g_assert_cmpvariant (one_variant, two_byteswapped);
+
+ if (g_variant_equal (two_variant, three_variant))
+ g_assert_cmpvariant (two_byteswapped, three_byteswapped);
+
+ g_variant_unref (three_byteswapped);
+ g_variant_unref (three_variant);
+ g_variant_unref (two_byteswapped);
+ g_variant_unref (two_variant);
+ g_variant_unref (one_variant);
tree_instance_free (tree);
g_free (one.data);
g_free (two.data);
+ g_free (three.data);
+ g_free (three_data_copy);
}
static void

View file

@ -1,146 +0,0 @@
From bf008669f26f70426ca30ee8cdcbd48e41a74718 Mon Sep 17 00:00:00 2001
From: Philip Withnall <pwithnall@endlessos.org>
Date: Thu, 15 Dec 2022 13:00:39 +0000
Subject: [PATCH 1/2] =?UTF-8?q?gvariant:=20Check=20offset=20table=20doesn?=
=?UTF-8?q?=E2=80=99t=20fall=20outside=20variant=20bounds?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
When dereferencing the first entry in the offset table for a tuple,
check that it doesnt fall outside the bounds of the variant first.
This prevents an out-of-bounds read from some non-normal tuples.
This bug was introduced in commit 73d0aa81c2575a5c9ae77d.
Includes a unit test, although the test will likely only catch the
original bug if run with asan enabled.
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
Fixes: #2840
oss-fuzz#54302
---
glib/gvariant-serialiser.c | 12 ++++++--
glib/tests/gvariant.c | 63 ++++++++++++++++++++++++++++++++++++++
2 files changed, 72 insertions(+), 3 deletions(-)
--- a/glib/gvariant-serialiser.c
+++ b/glib/gvariant-serialiser.c
@@ -979,7 +979,8 @@ gvs_tuple_get_member_bounds (GVariantSer
member_info = g_variant_type_info_member_info (value.type_info, index_);
- if (member_info->i + 1)
+ if (member_info->i + 1 &&
+ offset_size * (member_info->i + 1) <= value.size)
member_start = gvs_read_unaligned_le (value.data + value.size -
offset_size * (member_info->i + 1),
offset_size);
@@ -990,7 +991,8 @@ gvs_tuple_get_member_bounds (GVariantSer
member_start &= member_info->b;
member_start |= member_info->c;
- if (member_info->ending_type == G_VARIANT_MEMBER_ENDING_LAST)
+ if (member_info->ending_type == G_VARIANT_MEMBER_ENDING_LAST &&
+ offset_size * (member_info->i + 1) <= value.size)
member_end = value.size - offset_size * (member_info->i + 1);
else if (member_info->ending_type == G_VARIANT_MEMBER_ENDING_FIXED)
@@ -1001,11 +1003,15 @@ gvs_tuple_get_member_bounds (GVariantSer
member_end = member_start + fixed_size;
}
- else /* G_VARIANT_MEMBER_ENDING_OFFSET */
+ else if (member_info->ending_type == G_VARIANT_MEMBER_ENDING_OFFSET &&
+ offset_size * (member_info->i + 2) <= value.size)
member_end = gvs_read_unaligned_le (value.data + value.size -
offset_size * (member_info->i + 2),
offset_size);
+ else /* invalid */
+ member_end = G_MAXSIZE;
+
if (out_member_start != NULL)
*out_member_start = member_start;
if (out_member_end != NULL)
--- a/glib/tests/gvariant.c
+++ b/glib/tests/gvariant.c
@@ -5462,6 +5462,67 @@ test_normal_checking_tuple_offsets4 (voi
g_variant_unref (variant);
}
+/* This is a regression test that dereferencing the first element in the offset
+ * table doesnt dereference memory before the start of the GVariant. The first
+ * element in the offset table gives the offset of the final member in the
+ * tuple (the offset table is stored in reverse), and the position of this final
+ * member is needed to check that none of the tuple members overlap with the
+ * offset table
+ *
+ * See https://gitlab.gnome.org/GNOME/glib/-/issues/2840 */
+static void
+test_normal_checking_tuple_offsets5 (void)
+{
+ /* A tuple of type (sss) in normal form would have an offset table with two
+ * entries:
+ * - The first entry (lowest index in the table) gives the offset of the
+ * third `s` in the tuple, as the offset table is reversed compared to the
+ * tuple members.
+ * - The second entry (highest index in the table) gives the offset of the
+ * second `s` in the tuple.
+ * - The offset of the first `s` in the tuple is always 0.
+ *
+ * See §2.5.4 (Structures) of the GVariant specification for details, noting
+ * that the table is only layed out this way because all three members of the
+ * tuple have non-fixed sizes.
+ *
+ * Its not clear whether the 0xaa data of this variant is part of the strings
+ * in the tuple, or part of the offset table. It doesnt really matter. This
+ * is a regression test to check that the code to validate the offset table
+ * doesnt unconditionally try to access the first entry in the offset table
+ * by subtracting the table size from the end of the GVariant data.
+ *
+ * In this non-normal case, that would result in an address off the start of
+ * the GVariant data, and an out-of-bounds read, because the GVariant is one
+ * byte long, but the offset table is calculated as two bytes long (with 1B
+ * sized entries) from the tuples type.
+ */
+ const GVariantType *data_type = G_VARIANT_TYPE ("(sss)");
+ const guint8 data[] = { 0xaa };
+ gsize size = sizeof (data);
+ GVariant *variant = NULL;
+ GVariant *normal_variant = NULL;
+ GVariant *expected = NULL;
+
+ g_test_bug ("https://gitlab.gnome.org/GNOME/glib/-/issues/2840");
+
+ variant = g_variant_new_from_data (data_type, data, size, FALSE, NULL, NULL);
+ g_assert_nonnull (variant);
+
+ g_assert_false (g_variant_is_normal_form (variant));
+
+ normal_variant = g_variant_get_normal_form (variant);
+ g_assert_nonnull (normal_variant);
+
+ expected = g_variant_new_parsed ("('', '', '')");
+ g_assert_cmpvariant (expected, variant);
+ g_assert_cmpvariant (expected, normal_variant);
+
+ g_variant_unref (expected);
+ g_variant_unref (normal_variant);
+ g_variant_unref (variant);
+}
+
/* Test that an otherwise-valid serialised GVariant is considered non-normal if
* its offset table entries are too wide.
*
@@ -5711,6 +5772,8 @@ main (int argc, char **argv)
test_normal_checking_tuple_offsets3);
g_test_add_func ("/gvariant/normal-checking/tuple-offsets4",
test_normal_checking_tuple_offsets4);
+ g_test_add_func ("/gvariant/normal-checking/tuple-offsets5",
+ test_normal_checking_tuple_offsets5);
g_test_add_func ("/gvariant/normal-checking/tuple-offsets/minimal-sized",
test_normal_checking_tuple_offsets_minimal_sized);
g_test_add_func ("/gvariant/normal-checking/empty-object-path",

View file

@ -1,40 +0,0 @@
From 4d0bed8c4690f7a2692474ef6a570bd99ef45ef1 Mon Sep 17 00:00:00 2001
From: Philip Withnall <pwithnall@endlessos.org>
Date: Thu, 15 Dec 2022 16:49:28 +0000
Subject: [PATCH 2/2] gvariant: Propagate trust when getting a child of a
serialised variant
If a variant is trusted, that means all its children are trusted, so
ensure that their checked offsets are set as such.
This allows a lot of the offset table checks to be avoided when getting
children from trusted serialised tuples, which speeds things up.
No unit test is included because this is just a performance fix. If
there are other slownesses, or regressions, in serialised `GVariant`
performance, the fuzzing setup will catch them like it did this one.
This change does reduce the time to run the oss-fuzz reproducer from 80s
to about 0.7s on my machine.
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
Fixes: #2841
oss-fuzz#54314
---
glib/gvariant-core.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
--- a/glib/gvariant-core.c
+++ b/glib/gvariant-core.c
@@ -1196,8 +1196,8 @@ g_variant_get_child_value (GVariant *val
child->contents.serialised.bytes =
g_bytes_ref (value->contents.serialised.bytes);
child->contents.serialised.data = s_child.data;
- child->contents.serialised.ordered_offsets_up_to = s_child.ordered_offsets_up_to;
- child->contents.serialised.checked_offsets_up_to = s_child.checked_offsets_up_to;
+ child->contents.serialised.ordered_offsets_up_to = (value->state & STATE_TRUSTED) ? G_MAXSIZE : s_child.ordered_offsets_up_to;
+ child->contents.serialised.checked_offsets_up_to = (value->state & STATE_TRUSTED) ? G_MAXSIZE : s_child.checked_offsets_up_to;
return child;
}

View file

@ -1,60 +0,0 @@
From dc16dffed0480d0c8cdd6a05ede68263fc8723a9 Mon Sep 17 00:00:00 2001
From: Simon McVittie <smcv@collabora.com>
Date: Thu, 15 Dec 2022 12:51:37 +0000
Subject: [PATCH] gvariant-serialiser: Convert endianness of offsets
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
The array of offsets is little-endian, even on big-endian architectures
like s390x.
Fixes: ade71fb5 "gvariant: Dont allow child elements to overlap with each other"
Resolves: https://gitlab.gnome.org/GNOME/glib/-/issues/2839
Signed-off-by: Simon McVittie <smcv@collabora.com>
---
glib/gvariant-serialiser.c | 19 +++++++++++--------
1 file changed, 11 insertions(+), 8 deletions(-)
--- a/glib/gvariant-serialiser.c
+++ b/glib/gvariant-serialiser.c
@@ -712,17 +712,19 @@ gvs_variable_sized_array_n_children (GVa
/* Find the index of the first out-of-order element in @data, assuming that
* @data is an array of elements of given @type, starting at index @start and
* containing a further @len-@start elements. */
-#define DEFINE_FIND_UNORDERED(type) \
+#define DEFINE_FIND_UNORDERED(type, le_to_native) \
static gsize \
find_unordered_##type (const guint8 *data, gsize start, gsize len) \
{ \
gsize off; \
- type current, previous; \
+ type current_le, previous_le, current, previous; \
\
- memcpy (&previous, data + start * sizeof (current), sizeof (current)); \
+ memcpy (&previous_le, data + start * sizeof (current), sizeof (current)); \
+ previous = le_to_native (previous_le); \
for (off = (start + 1) * sizeof (current); off < len * sizeof (current); off += sizeof (current)) \
{ \
- memcpy (&current, data + off, sizeof (current)); \
+ memcpy (&current_le, data + off, sizeof (current)); \
+ current = le_to_native (current_le); \
if (current < previous) \
break; \
previous = current; \
@@ -730,10 +732,11 @@ gvs_variable_sized_array_n_children (GVa
return off / sizeof (current) - 1; \
}
-DEFINE_FIND_UNORDERED (guint8);
-DEFINE_FIND_UNORDERED (guint16);
-DEFINE_FIND_UNORDERED (guint32);
-DEFINE_FIND_UNORDERED (guint64);
+#define NO_CONVERSION(x) (x)
+DEFINE_FIND_UNORDERED (guint8, NO_CONVERSION);
+DEFINE_FIND_UNORDERED (guint16, GUINT16_FROM_LE);
+DEFINE_FIND_UNORDERED (guint32, GUINT32_FROM_LE);
+DEFINE_FIND_UNORDERED (guint64, GUINT64_FROM_LE);
static GVariantSerialised
gvs_variable_sized_array_get_child (GVariantSerialised value,

View file

@ -1,80 +0,0 @@
From: Simon McVittie <smcv@debian.org>
Date: Mon, 18 Dec 2017 18:06:05 +0000
Subject: gwakeuptest: Be less parallel unless invoked with -m slow
This is a workaround for test failures on the reproducible-builds
infrastructure, where a multi-threaded stress-test sometimes takes longer
to finish on x86_64 than it would have done on slow architectures like
arm and mips on the official Debian autobuilders. It is not clear why.
This change will make this test more likely to pass, but less likely to
detect bugs.
Signed-off-by: Simon McVittie <smcv@debian.org>
Bug-Debian: https://bugs.debian.org/884659
Forwarded: no
---
glib/tests/gwakeuptest.c | 17 +++++++++++++----
1 file changed, 13 insertions(+), 4 deletions(-)
diff --git a/glib/tests/gwakeuptest.c b/glib/tests/gwakeuptest.c
index b37fb43..a9bef21 100644
--- a/glib/tests/gwakeuptest.c
+++ b/glib/tests/gwakeuptest.c
@@ -89,6 +89,9 @@ struct context
#define NUM_TOKENS 5
#define TOKEN_TTL 100000
+static gint num_threads = NUM_THREADS;
+static gint token_ttl = TOKEN_TTL;
+
static struct context contexts[NUM_THREADS];
static GThread *threads[NUM_THREADS];
static GWakeup *last_token_wakeup;
@@ -158,7 +161,7 @@ dispatch_token (struct token *token)
struct context *ctx;
gint next_ctx;
- next_ctx = g_test_rand_int_range (0, NUM_THREADS);
+ next_ctx = g_test_rand_int_range (0, num_threads);
ctx = &contexts[next_ctx];
token->owner = ctx;
token->ttl--;
@@ -213,6 +216,12 @@ test_threaded (void)
{
gint i;
+ if (!g_test_slow ())
+ {
+ num_threads = NUM_THREADS / 10;
+ token_ttl = TOKEN_TTL / 10;
+ }
+
/* make sure we don't block forever */
alarm (60);
@@ -230,7 +239,7 @@ test_threaded (void)
last_token_wakeup = g_wakeup_new ();
/* create contexts, assign to threads */
- for (i = 0; i < NUM_THREADS; i++)
+ for (i = 0; i < num_threads; i++)
{
context_init (&contexts[i]);
threads[i] = g_thread_new ("test", thread_func, &contexts[i]);
@@ -238,13 +247,13 @@ test_threaded (void)
/* dispatch tokens */
for (i = 0; i < NUM_TOKENS; i++)
- dispatch_token (token_new (TOKEN_TTL));
+ dispatch_token (token_new (token_ttl));
/* wait until all tokens are gone */
wait_for_signaled (last_token_wakeup);
/* ask threads to quit, join them, cleanup */
- for (i = 0; i < NUM_THREADS; i++)
+ for (i = 0; i < num_threads; i++)
{
context_quit (&contexts[i]);
g_thread_join (threads[i]);

41
debian/patches/series vendored
View file

@ -1,41 +0,0 @@
01_gettext-desktopfiles.patch
0001-timer-test-use-volatile-for-locals.patch
gwakeuptest-Be-less-parallel-unless-invoked-with-m-slow.patch
debian/02_gettext-desktopfiles-ubuntu.patch
debian/03_disble_glib_compile_schemas_warning.patch
debian/06_thread_test_ignore_prctl_fail.patch
debian/closures-test-Skip-on-arm-unless-flaky-tests-are-allowed.patch
debian/Disable-some-tests-on-slow-architectures-which-keep-faili.patch
debian/Skip-test-which-performs-some-unreliable-floating-point-c.patch
debian/Skip-unreliable-gdbus-threading-tests--by-default.patch
debian/gmenumodel-test-Mark-as-flaky.patch
debian/gvariant-test-Don-t-run-at-build-time-on-mips.patch
debian/testfilemonitor-Skip-if-we-are-avoiding-flaky-tests.patch
debian/gdbus-server-auth-Normally-skip-flaky-DBUS_COOKIE_SHA1-te.patch
debian/Skip-memory-monitor-dbus-test-if-not-specifically-request.patch
debian/Add-extra-debug-to-memory-monitor-dbus-test.patch
debian/tests-Skip-debugcontroller-test.patch
debian/gdesktopappinfo-Recognize-gnome-console-as-a-terminal-app.patch
0001-gio-Make-portal-support-aware-of-snaps.patch
gvariant-security-1-01.patch
gvariant-security-1-02.patch
gvariant-security-1-03.patch
gvariant-security-1-04.patch
gvariant-security-1-05.patch
gvariant-security-1-06.patch
gvariant-security-1-07.patch
gvariant-security-1-08.patch
gvariant-security-1-09.patch
gvariant-security-1-10.patch
gvariant-security-1-11.patch
gvariant-security-1-12.patch
gvariant-security-1-13.patch
gvariant-security-1-14.patch
gvariant-security-1-15.patch
gvariant-security-1-16.patch
gvariant-security-1-17.patch
gvariant-security-1-18.patch
gvariant-security-2-1.patch
gvariant-security-2-2.patch
gvariant-security-3-1.patch
disable-setting-ACL-attributes-see-https-code.evin.team-e.patch

296
debian/rules vendored
View file

@ -1,296 +0,0 @@
#!/usr/bin/make -f
binaries := $(shell dh_listpackages)
export DEB_BUILD_MAINT_OPTIONS=hardening=+bindnow
# Ensure the build aborts when there are still references to undefined symbols
DEB_LDFLAGS_MAINT_APPEND += -Wl,-z,defs
# NB: do NOT use -Wl,--as-needed to build glib; for instance the link to
# pthread is carefully crafted to allow dlopen()ing pthread-using libs; see
# https://marc.info/?i=1257999019.21780.15.camel@marzipan aka
# https://mail.gnome.org/archives/gtk-devel-list/2009-November/msg00096.html
DEB_LDFLAGS_MAINT_APPEND += -Wl,--no-as-needed
# Make the linker work a bit harder so dynamic loading can be done faster
DEB_LDFLAGS_MAINT_APPEND += -Wl,-O1
include /usr/share/dpkg/default.mk
%:
dh $@
ifneq ($(filter hppa,$(DEB_HOST_ARCH_CPU)),)
stack_grows_up = true
else
stack_grows_up = false
endif
ifneq ($(filter kfreebsd,$(DEB_HOST_ARCH_OS)),)
have_non_stub_xattr = false
else
have_non_stub_xattr = true
endif
export DH_MESON_CROSS_FILE = debian/cross.txt
# We edit the debcrossgen output to work around unimplemented feature
# request https://bugs.debian.org/912559
override_dh_auto_configure:
ifneq ($(DEB_HOST_ARCH),$(DEB_BUILD_ARCH))
/usr/share/meson/debcrossgen \
-o debian/cross.txt.in
debian/set-cross-properties \
have_c99_snprintf=true \
have_c99_vsnprintf=true \
have_strlcpy=false \
have_unix98_printf=true \
growing_stack=$(stack_grows_up) \
< debian/cross.txt.in > debian/cross.txt
endif
dh_auto_configure \
--builddirectory=debian/build/deb \
-- \
$(DEB_CONFIGURE_EXTRA_FLAGS) \
$(DEB_CONFIGURE_FLAGS_deb) \
$(NULL)
ifneq ($(filter %-udeb,$(binaries)),)
dh_auto_configure \
--builddirectory=debian/build/udeb \
-- \
$(DEB_CONFIGURE_EXTRA_FLAGS) \
$(DEB_CONFIGURE_FLAGS_udeb) \
$(NULL)
endif
override_dh_clean:
rm -rf $(CURDIR)/debian/build \
$(CURDIR)/debian/install
dh_clean -Xorg.gtk.test.gschema.xml.orig -Xorg.gtk.test.gschema.override.orig
override_dh_makeshlibs:
dh_makeshlibs -plibglib2.0-tests -n
dh_makeshlibs --remaining-packages --add-udeb=libglib2.0-udeb -Xlibgiofam.so -- -c4
# (Ubuntu-specific)
# Don't strip translations from the installed tests; makes them environment dependent.
override_dh_translations:
dh_translations -Xinstalled-tests
# Do not clutter $HOME with ~/.dbus-keyrings and avoid failure on the buildds
# where creating /home/buildd/.dbus-keyrings fails
export HOME=$(CURDIR)/debian/build
# Make sure that everything that uses D-Bus is creating its own temporary
# session rather than polluting the developer's (or failing, on buildds)
export DBUS_SESSION_BUS_ADDRESS=this-should-not-be-used-and-will-fail:
ifeq ($(DEB_HOST_ARCH_OS), linux)
handle_test_failure := exit $$?
else
handle_test_failure := true
endif
# Upstream test timeouts assume an otherwise unloaded system, but that
# isn't necessarily the case for a porterbox or multiple parallel builds
test_timeout_multiplier = 3
ifneq ($(filter arm hppa mips% sparc%,$(DEB_HOST_ARCH_CPU)),)
$(info Slow architecture detected, increasing test timeout)
test_timeout_multiplier = 5
endif
ifneq ($(filter m68k riscv64 sh4,$(DEB_HOST_ARCH_CPU)),)
$(info Architecture with qemu buildds detected, increasing test timeout a lot)
test_timeout_multiplier = 20
endif
override_dh_auto_test-arch:
ifeq (,$(filter nocheck,$(DEB_BUILD_OPTIONS)))
# Remove LD_PRELOAD so we don't run with fakeroot, which makes dbus-related tests fail
# First run the non-flaky tests, and fail the build if they fail (on linux)
env -u LD_PRELOAD \
DEB_BUILD_TIME_TESTS=1 \
LC_ALL=C.UTF-8 \
MESON_TESTTHREADS=1 \
debian/tests/run-with-locales \
--generate de_DE=ISO-8859-1 \
--generate de_DE.utf8 \
--generate de_DE@euro.utf8 \
--generate el_GR.utf8 \
--generate en_GB=ISO-8859-1 \
--generate en_GB.utf8 \
--generate en_US=ISO-8859-1 \
--generate en_US.utf8 \
--generate es_ES.utf8 \
--generate fa_IR=UTF-8 \
--generate fa_IR.utf8 \
--generate fr_FR.utf8 \
--generate hr_HR.utf8 \
--generate ja_JP.utf8 \
--generate ja_JP.EUC-JP \
--generate lt_LT.utf8 \
--generate pl_PL=ISO-8859-2 \
--generate pl_PL.ISO-8859-2 \
--generate pl_PL.utf8 \
--generate ru_RU=ISO-8859-5 \
--generate ru_RU.utf8 \
--generate sr_RS=UTF-8 \
--generate sr_RS@latin=UTF-8 \
--generate sv_SE=ISO-8859-1 \
--generate sv_SE.utf8 \
--generate tr_TR=ISO-8859-9 \
--generate tr_TR.utf8 \
--generate tt_RU=UTF-8 \
--generate tt_RU.utf8 \
--generate tt_RU@iqtelif=UTF-8 \
-- \
meson test -C debian/build/deb \
--no-rebuild \
--num-processes 1 \
--timeout-multiplier $(test_timeout_multiplier) \
--no-suite flaky \
--verbose \
|| $(handle_test_failure)
# and then run the flaky ones, but ignore them failing
env -u LD_PRELOAD \
DEB_BUILD_TIME_TESTS=1 \
LC_ALL=C.UTF-8 \
MESON_TESTTHREADS=1 \
meson test -C debian/build/deb \
--no-rebuild \
--num-processes 1 \
--timeout-multiplier $(test_timeout_multiplier) \
--suite flaky \
--verbose \
|| true
endif
# Skip most build-time tests if all we are building is documentation;
# running them once per architecture is plenty. As an exception, do run the
# documentation completeness checks, which won't normally be run on
# architecture-specific buildds (except in Ubuntu).
override_dh_auto_test-indep:
meson test -C debian/build/deb \
--no-rebuild \
--num-processes 1 \
--timeout-multiplier $(test_timeout_multiplier) \
--verbose \
gio-doc-check glib-doc-check gobject-doc-check \
|| $(handle_test_failure)
# Let's get failing tests' stdout and stderr so we have some information when
# a build fails
export VERBOSE=1
ifeq ($(DEB_HOST_ARCH_OS),linux)
enable_libmount := enabled
enable_selinux := enabled
else
enable_libmount := disabled
enable_selinux := disabled
endif
ifneq ($(filter hurd,$(DEB_HOST_ARCH_OS)),)
use_fam := true
else
use_fam := false
endif
DEB_CONFIGURE_FLAGS_deb := \
--default-library both \
-Dfam=$(use_fam) \
-Dinstalled_tests=true \
-Dlibelf=enabled \
-Dlibmount=$(enable_libmount) \
-Dman=true \
-Dselinux=$(enable_selinux) \
-Dsystemtap=true \
-Dxattr=$(have_non_stub_xattr) \
$(NULL)
ifneq ($(filter libglib2.0-doc,$(binaries)),)
DEB_CONFIGURE_FLAGS_deb += -Dgtk_doc=true
else
DEB_CONFIGURE_FLAGS_deb += -Dgtk_doc=false
endif
DEB_CONFIGURE_FLAGS_udeb := \
--default-library shared \
-Dgtk_doc=false \
-Dinstalled_tests=false \
-Dlibmount=disabled \
-Dselinux=disabled \
-Dxattr=$(have_non_stub_xattr) \
$(NULL)
override_dh_auto_build:
mkdir -p debian/tmp-xdg-runtime-dir
dh_auto_build --builddirectory=debian/build/deb
ifneq ($(filter %-udeb,$(binaries)),)
dh_auto_build --builddirectory=debian/build/udeb
endif
override_dh_auto_install:
set -e; for script in postinst postrm triggers; do \
sed -e"s/#MULTIARCH#/$(DEB_HOST_MULTIARCH)/g" \
-e"s/#ARCH#/$(DEB_HOST_ARCH)/g" \
debian/libglib2.0-0.$$script.in \
> debian/libglib2.0-0.$$script ; \
done
ifneq ($(filter %-udeb,$(binaries)),)
dh_auto_install -plibglib2.0-udeb --builddirectory=debian/build/udeb --destdir=debian/install/udeb
endif
dh_auto_install --remaining-packages --builddirectory=debian/build/deb --destdir=debian/install/deb
override_dh_python3:
# dh_python3 can't process both a private directory and /usr/bin
# in the same invocation
dh_python3 -plibglib2.0-dev-bin /usr/share/glib-2.0/codegen
dh_python3 -plibglib2.0-tests --no-ext-rename /usr/libexec/installed-tests/glib
dh_python3
override_dh_install:
# Unwanted bits from the .deb build
rm -fr debian/install/deb/usr/share/glib-2.0/codegen/__pycache__
ifneq ($(filter %-udeb,$(binaries)),)
# Unwanted bits from the .udeb build
rm -f debian/install/udeb/usr/lib/*/*.so
rm -fr debian/install/udeb/usr/share/gdb
rm -fr debian/install/udeb/usr/share/gettext/its
rm -fr debian/install/udeb/usr/share/glib-2.0/codegen
rm -fr debian/install/udeb/usr/share/glib-2.0/gdb
rm -fr debian/install/udeb/usr/share/glib-2.0/valgrind
rm -fr debian/install/udeb/usr/share/man
dh_install -plibglib2.0-udeb --sourcedir=debian/install/udeb
endif
ifneq ($(filter %-tests,$(binaries)),)
sed -i -e '/^#!.*/,1 d' debian/install/deb/usr/libexec/installed-tests/glib/taptestrunner.py
endif
ifneq ($(filter hurd,$(DEB_HOST_ARCH_OS)),)
dh_install -plibglib2.0-0 --sourcedir=debian/install/deb usr/lib/${DEB_HOST_MULTIARCH}/gio/modules/libgiofam.so usr/lib/${DEB_HOST_MULTIARCH}/gio/modules
endif
dh_install --remaining-packages --sourcedir=debian/install/deb
install -D -t debian/libglib2.0-0/usr/share/glib-2.0/ debian/clean-up-unmanaged-libraries
install -D -t debian/libglib2.0-0/usr/lib/${DEB_HOST_MULTIARCH}/glib-2.0/ debian/gio-launch-desktop
override_dh_dwz:
dh_dwz -Nlibglib2.0-udeb
# debhelper >= 13.4 makes all of /usr/libexec executable, which is not
# quite right for installed-tests
override_dh_fixperms:
dh_fixperms -Xusr/libexec/installed-tests
ifneq ($(filter %-tests,$(binaries)),)
chmod --changes u=rw,og=r debian/libglib2.0-tests/usr/libexec/installed-tests/*/*.so
chmod --changes u=rw,og=r debian/libglib2.0-tests/usr/libexec/installed-tests/*/*/*.so
chmod --recursive --changes a+rX,u+w,og-w debian/libglib2.0-tests/usr/libexec/installed-tests
endif
override_dh_missing:
dh_missing --sourcedir=debian/install/deb
ifneq ($(filter %-udeb,$(binaries)),)
dh_missing --sourcedir=debian/install/udeb
endif

View file

@ -1,22 +0,0 @@
#!/usr/bin/python3
import sys
def write_properties(properties):
for prop in properties:
k, v = prop.split('=', 1)
print('{} = {}'.format(k, v))
if __name__ == '__main__':
for line in sys.stdin:
sys.stdout.write(line)
if line.strip() == '[properties]':
write_properties(sys.argv[1:])
done = True
if not done:
print('[properties]')
write_properties(sys.argv[1:])

10
debian/shlibs.local vendored
View file

@ -1,10 +0,0 @@
libgio-2.0 0 libglib2.0-0 (= ${binary:Version})
libglib-2.0 0 libglib2.0-0 (= ${binary:Version})
libgmodule-2.0 0 libglib2.0-0 (= ${binary:Version})
libgobject-2.0 0 libglib2.0-0 (= ${binary:Version})
libgthread-2.0 0 libglib2.0-0 (= ${binary:Version})
udeb: libgio-2.0 0 libglib2.0-udeb (= ${binary:Version})
udeb: libglib-2.0 0 libglib2.0-udeb (= ${binary:Version})
udeb: libgmodule-2.0 0 libglib2.0-udeb (= ${binary:Version})
udeb: libgobject-2.0 0 libglib2.0-udeb (= ${binary:Version})
udeb: libgthread-2.0 0 libglib2.0-udeb (= ${binary:Version})

View file

@ -1 +0,0 @@
3.0 (quilt)

170
debian/tests/bug896019 vendored
View file

@ -1,170 +0,0 @@
#!/bin/bash
set -e
. debian/tests/lib.sh
cd "$AUTOPKGTEST_TMP"
biarch=
getopt_temp="help"
getopt_temp="$getopt_temp,biarch"
getopt_temp="$(getopt -o '' --long "$getopt_temp" -n "$me" -- "$@")"
eval "set -- $getopt_temp"
while [ "$#" -gt 0 ]
do
case "$1" in
(--biarch)
biarch=yes
shift
;;
(--)
shift
break
;;
(-*)
warning "Unknown option: $1"
usage 2
;;
(*)
break
;;
esac
done
system_arch="${DEB_HOST_ARCH:-"$(dpkg --print-architecture)"}"
multiarch="${DEB_HOST_MULTIARCH:-"$(dpkg-architecture -a"$system_arch" -qDEB_HOST_MULTIARCH)"}"
foreign_arch=
foreign_multiarch=
if [ -n "$biarch" ]; then
case "$system_arch" in
(amd64)
foreign_arch="i386"
foreign_multiarch="i386-linux-gnu"
;;
(arm64)
foreign_arch="armhf"
foreign_multiarch="arm-linux-gnueabihf"
;;
(*)
echo "1..0 # SKIP - no secondary architecture" >&7
exit 77
esac
fi
if [ -n "$foreign_arch" ]; then
require dpkg --add-architecture "$foreign_arch"
require_apt "$foreign_arch"
fi
if [ -n "$foreign_arch" ]; then
multiarchs=("$multiarch" "$foreign_multiarch")
else
multiarchs=("$multiarch")
fi
require_apt_stretch
package=libglib2.0-0
old_version=2.50.3-2+deb9u2
soname=libglib-2.0.so.0
other_sonames=(libgio-2.0.so.0 libgmodule-2.0.so.0 libgobject-2.0.so.0 libgthread-2.0.so.0)
tail=5000.3
if ! new_version=$(dpkg-query -W -f '${Version}' "$package:$system_arch"); then
echo "1..0 # SKIP - unable to get version of $package:$system_arch" >&7
exit 77
fi
if ! apt-get download "$package=$old_version"; then
echo "1..0 # SKIP - unable to download $package=$old_version" >&7
exit 77
fi
if [ -n "$foreign_arch" ] && ! apt-get download "$package:$foreign_arch=$old_version"; then
echo "1..0 # SKIP - unable to download $package:$foreign_arch=$old_version" >&7
exit 77
fi
if [ -n "$foreign_arch" ]; then
require apt-get -y install --reinstall "$package=$new_version" "$package:$foreign_arch=$new_version"
good_foreign_realpath="$(readlink -f "/usr/lib/$foreign_multiarch/$soname")"
else
require apt-get -y install --reinstall "$package=$new_version"
good_foreign_realpath=
fi
good_realpath="$(readlink -f "/usr/lib/$multiarch/$soname")"
# Pretend the version from stretch got stuck on the system somehow.
# (This is the wrong way to use dpkg-deb, never do this in production.)
require dpkg-deb --vextract "${package}_${old_version}_${system_arch}.deb" .
if [ -n "$foreign_arch" ]; then
require dpkg-deb --vextract "${package}_${old_version}_${foreign_arch}.deb" .
fi
for ma in "${multiarchs[@]}"; do
cp -a ./lib/"$ma"/"$soname" /lib/"$ma"/
cp -a ./lib/"$ma"/"$soname".* /lib/"$ma"/
for other in "${other_sonames[@]}"; do
cp -a ./usr/lib/"$ma"/"$other" /usr/lib/"$ma"/
cp -a ./usr/lib/"$ma"/"$other".* /usr/lib/"$ma"/
done
done
assert_succeeds ldconfig --verbose
for ma in "${multiarchs[@]}"; do
echo "Status before reinstalling $package"
assert_succeeds ls -il "/lib/$ma/$soname"
assert_succeeds ls -il "/lib/$ma/$soname".*
assert_succeeds ls -il "/lib/$ma/$soname.$tail"
assert_succeeds ls -il "/usr/lib/$ma/$soname"
assert_succeeds ls -il "/usr/lib/$ma/$soname".*
done
for other in "$soname" "${other_sonames[@]}"; do
echo "Running 'true' with $other preloaded to see what we get..."
env LD_DEBUG=libs LD_PRELOAD="$other" true || true
done
if [ -n "$foreign_arch" ]; then
assert_succeeds apt-get -y install --reinstall "$package:$system_arch=$new_version" "$package:$foreign_arch=$new_version"
else
assert_succeeds apt-get -y install --reinstall "$package:$system_arch=$new_version"
fi
for ma in "${multiarchs[@]}"; do
if [ "/usr/lib/$ma" -ef "/lib/$ma" ]; then
echo "Merged-/usr system"
assert_status 1 test "/usr/lib/$ma/$soname" -ef "/usr/lib/$ma/$soname.$tail"
else
echo "Non-merged-/usr system"
assert_succeeds ls -il "/lib/$ma/removed-by-upgrade-bug896019/"
assert_status 1 test -e "/lib/$ma/$soname.$tail"
assert_status 1 test -e "/lib/$ma/$soname"
assert_succeeds test -e "/usr/lib/$ma/$soname"
fi
done
assert_succeeds test "/usr/lib/$multiarch/$soname" -ef "$good_realpath"
if [ -n "$foreign_arch" ]; then
assert_succeeds test "/usr/lib/$foreign_multiarch/$soname" -ef "$good_foreign_realpath"
fi
for other in "$soname" "${other_sonames[@]}"; do
env LD_DEBUG=libs LD_PRELOAD="$other" true
done
finish
# vim:set sw=4 sts=4 et:

View file

@ -1,2 +0,0 @@
#!/bin/sh
exec debian/tests/bug896019 --biarch

143
debian/tests/build vendored
View file

@ -1,143 +0,0 @@
#!/bin/sh
# autopkgtest check: Build and run a program against glib, to verify that the
# headers and pkg-config file are installed correctly
# (C) 2012,2019 Canonical Ltd.
# (C) 2018 Simon McVittie
# Authors: Martin Pitt <martin.pitt@ubuntu.com>, Simon McVittie
set -eux
mode=dynamic
getopt_temp="$(getopt -o '' --long 'static' -n debian/tests/build -- "$@")"
eval set -- "$getopt_temp"
while true; do
case "$1" in
(--static)
mode=static
shift
continue
;;
(--)
shift
break
;;
(*)
echo "getopt: Internal error" >&2
exit 2
esac
done
WORKDIR=$(mktemp -d)
trap 'rm -rf "${WORKDIR}"' 0 INT QUIT ABRT PIPE TERM
cd "${WORKDIR}"
if [ -n "${DEB_HOST_GNU_TYPE:-}" ]; then
CROSS_COMPILE="${DEB_HOST_GNU_TYPE}-"
else
CROSS_COMPILE=
fi
cat <<EOF > glib.c
#include <glib.h>
int main(void)
{
g_assert_cmpint (g_strcmp0 (NULL, "hello"), ==, -1);
g_assert_cmpstr (g_getenv ("foo"), ==, "bar");
return 0;
}
EOF
cat <<EOF > gobject.c
#include <glib-object.h>
int main(void)
{
g_assert_cmpuint (G_TYPE_OBJECT, !=, G_TYPE_INVALID);
return 0;
}
EOF
cat <<EOF > gio.c
#include <gio/gio.h>
int main(void)
{
g_assert_cmpuint (G_TYPE_FILE, !=, G_TYPE_INVALID);
return 0;
}
EOF
cat <<EOF > gio-unix.c
#include <gio/gunixfdlist.h>
int main(void)
{
g_assert_cmpuint (G_TYPE_UNIX_FD_LIST, !=, G_TYPE_INVALID);
return 0;
}
EOF
cat <<EOF > gmodule.c
#include <gmodule.h>
int main(void)
{
GModule *module;
g_assert_true (g_module_supported ());
module = g_module_open (NULL, 0);
g_assert_nonnull (module);
g_assert_true (g_module_close (module));
return 0;
}
EOF
cat <<EOF > gthread.c
#include <glib.h>
static gpointer
other_cb (gpointer nil)
{
return "hello";
}
int main(void)
{
GThread *other;
gpointer ret;
other = g_thread_new ("other", other_cb, NULL);
g_assert_nonnull (other);
ret = g_thread_join (other);
g_assert_cmpstr (ret, ==, "hello");
return 0;
}
EOF
for lib in glib gobject gio gio-unix gmodule gthread; do
cflags=
pcflags=
packages="${lib}-2.0"
case "$mode" in
(static)
cflags=-static
pcflags=--static
case "$lib" in
(gio|gio-unix)
# GIO depends on libmount which no longer supports
# being linked statically
continue
;;
esac
;;
esac
# shellcheck disable=SC2046
${CROSS_COMPILE}gcc $cflags -o ${lib}-$mode ${lib}.c $(${CROSS_COMPILE}pkg-config $pcflags --cflags --libs ${packages})
echo "build ($lib, $mode): OK"
[ -x ${lib}-$mode ]
foo=bar ./${lib}-$mode
echo "run ($lib, $mode): OK"
done

View file

@ -1,2 +0,0 @@
#!/bin/sh
exec debian/tests/build --static

15
debian/tests/control vendored
View file

@ -1,15 +0,0 @@
Tests: build build-static
Depends: libglib2.0-dev, build-essential
Restrictions: allow-stderr superficial
Tests: installed-tests
Depends: dbus (>= 1.8), dbus-x11, gnome-desktop-testing, libglib2.0-tests, locales | locales-all, xauth, xvfb
Restrictions: allow-stderr
Tests: flaky
Depends: dbus (>= 1.8), dbus-x11, gnome-desktop-testing, libglib2.0-tests, locales | locales-all, xauth, xvfb
Restrictions: allow-stderr flaky
Tests: bug896019 bug896019-biarch
Depends: dpkg-dev, libglib2.0-0
Restrictions: allow-stderr, breaks-testbed, needs-root, skippable

72
debian/tests/flaky vendored
View file

@ -1,72 +0,0 @@
#!/bin/sh
# autopkgtest check: Run the installed-tests to verify glib works correctly
# This part runs tests that have been marked as opt-in due to being flaky
# on at least some architectures.
# (C) 2013 Canonical Ltd.
# (C) 2019 Collabora Ltd.
set -eu
NULL=
export DEB_ALLOW_FLAKY_TESTS=1
# Disable gvfs if it happens to be installed. We want to test the built-in
# stuff
export GIO_USE_VFS=local
export GIO_USE_VOLUME_MONITOR=unix
export XDG_RUNTIME_DIR="$AUTOPKGTEST_TMP"
printf "Running as: "; id -a
printf "passwd entry: "; getent passwd "$(id -u)" || echo "(exit status $?)"
printf "group entry: "; getent group "$(id -g)" || echo "(exit status $?)"
echo "Environment:"
env | LC_ALL=C sort -u
exec dbus-run-session -- \
xvfb-run -a \
debian/tests/run-with-locales \
--generate de_DE=ISO-8859-1 \
--generate de_DE.utf8 \
--generate de_DE@euro.utf8 \
--generate el_GR.utf8 \
--generate en_GB=ISO-8859-1 \
--generate en_GB.utf8 \
--generate en_US=ISO-8859-1 \
--generate en_US.utf8 \
--generate es_ES.utf8 \
--generate fa_IR=UTF-8 \
--generate fa_IR.utf8 \
--generate fr_FR.utf8 \
--generate hr_HR.utf8 \
--generate ja_JP.utf8 \
--generate ja_JP.EUC-JP \
--generate lt_LT.utf8 \
--generate pl_PL=ISO-8859-2 \
--generate pl_PL.ISO-8859-2 \
--generate pl_PL.utf8 \
--generate ru_RU=ISO-8859-5 \
--generate ru_RU.utf8 \
--generate sr_RS=UTF-8 \
--generate sr_RS@latin=UTF-8 \
--generate sv_SE=ISO-8859-1 \
--generate sv_SE.utf8 \
--generate tr_TR=ISO-8859-9 \
--generate tr_TR.utf8 \
--generate tt_RU=UTF-8 \
--generate tt_RU.utf8 \
--generate tt_RU@iqtelif=UTF-8 \
-- \
gnome-desktop-testing-runner \
glib/closure-refcount.test \
glib/debugcontroller.test \
glib/gdbus-server-auth.test \
glib/gdbus-threading.test \
glib/gmenumodel.test \
glib/mainloop.test \
glib/memory-monitor-dbus.test \
glib/socket.test \
glib/testfilemonitor.test \
glib/timeout.test \
glib/timer.test \
${NULL}

View file

@ -1,55 +0,0 @@
#!/bin/sh
# autopkgtest check: Run the installed-tests to verify glib works correctly
# (C) 2013 Canonical Ltd.
# Author: Iain Lane <iain.lane@canonical.com>
set -eu
# Disable gvfs if it happens to be installed. We want to test the built-in
# stuff
export GIO_USE_VFS=local
export GIO_USE_VOLUME_MONITOR=unix
export XDG_RUNTIME_DIR="$AUTOPKGTEST_TMP"
printf "Running as: "; id -a
printf "passwd entry: "; getent passwd "$(id -u)" || echo "(exit status $?)"
printf "group entry: "; getent group "$(id -g)" || echo "(exit status $?)"
echo "Environment:"
env | LC_ALL=C sort -u
exec dbus-run-session -- \
xvfb-run -a \
debian/tests/run-with-locales \
--generate de_DE=ISO-8859-1 \
--generate de_DE.utf8 \
--generate de_DE@euro.utf8 \
--generate el_GR.utf8 \
--generate en_GB=ISO-8859-1 \
--generate en_GB.utf8 \
--generate en_US=ISO-8859-1 \
--generate en_US.utf8 \
--generate es_ES.utf8 \
--generate fa_IR=UTF-8 \
--generate fa_IR.utf8 \
--generate fr_FR.utf8 \
--generate hr_HR.utf8 \
--generate ja_JP.utf8 \
--generate ja_JP.EUC-JP \
--generate lt_LT.utf8 \
--generate pl_PL=ISO-8859-2 \
--generate pl_PL.ISO-8859-2 \
--generate pl_PL.utf8 \
--generate ru_RU=ISO-8859-5 \
--generate ru_RU.utf8 \
--generate sr_RS=UTF-8 \
--generate sr_RS@latin=UTF-8 \
--generate sv_SE=ISO-8859-1 \
--generate sv_SE.utf8 \
--generate tr_TR=ISO-8859-9 \
--generate tr_TR.utf8 \
--generate tt_RU=UTF-8 \
--generate tt_RU.utf8 \
--generate tt_RU@iqtelif=UTF-8 \
-- \
gnome-desktop-testing-runner glib

124
debian/tests/lib.sh vendored
View file

@ -1,124 +0,0 @@
#!/bin/sh
test_num=0
fail=0
# TAP output goes to fd 7, which is our original stdout
exec 7>&1
# Other stdout goes to our original stderr
exec >&2
require () {
if ! "$@"; then
echo "1..0 # SKIP - command failed: $*" >&7
exit 77
fi
}
require_apt_stretch () {
mirror="$(perl -ne 'if (m{^deb\s+(https?://[-\w.:]+)/debian/?\s}) { print "$1\n"; exit; }' /etc/apt/sources.list /etc/apt/sources.list.d/*)"
if [ -n "$mirror" ]; then
echo >> /etc/apt/sources.list
echo "deb $mirror/debian stretch main" >> /etc/apt/sources.list
else
echo "1..0 # SKIP - unable to guess how to set up an apt source for stretch" >&7
exit 77
fi
require_apt
}
require_apt () {
local arch="${1-}"
if [ -n "${DEB_HOST_ARCH-}" ]; then
host_suffix=":${DEB_HOST_ARCH}"
fi
if ! apt-get -y update; then
echo "1..0 # SKIP - apt not configured?" >&7
exit 77
fi
if [ -n "$arch" ]; then
if ! apt-get -y install libc6:$arch; then
echo "1..0 # SKIP - cannot install libc6:$arch" >&7
exit 77
fi
else
if ! apt-get -y install hello; then
echo "1..0 # SKIP - apt not configured?" >&7
exit 77
fi
fi
}
assert_succeeds () {
assert_status 0 "$@"
}
assert_status () {
local expected="$1"
local e
shift
test_num=$(( $test_num + 1 ))
echo "# $*"
if "$@"; then
if [ "x$expected" = x0 ]; then
echo "ok $test_num - “$*" >&7
else
echo "not ok $test_num - “$*” succeeded but should have failed" >&7
fail=1
fi
else
e="$?"
if [ "x$expected" = "x$e" ] || [ "x$expected" = xfailure ]; then
echo "ok $test_num - “$*” failed with status $e as expected" >&7
else
echo "not ok $test_num - “$*” expected status $expected, got $e" >&7
fail=1
fi
fi
}
assert_output () {
local expected="$1"
shift
local really
test_num=$(( $test_num + 1 ))
echo "# $*"
if really="$("$@")"; then
if [ "x$expected" = "x$really" ]; then
echo "ok $test_num - “$*” returned “$really” as expected" >&7
else
echo "not ok $test_num - expected “$*” to output “$*”, got “$really" >&7
fail=1
fi
else
e="$?"
echo "not ok $test_num - “$*” failed with exit status $e" >&7
fail=1
fi
}
ok () {
test_num=$(( $test_num + 1 ))
echo "ok $test_num - $*" >&7
}
skip_to_the_end () {
test_num=$(( $test_num + 1 ))
echo "not ok $test_num # SKIP $*" >&7
finish
}
finish () {
echo "1..$test_num" >&7
exit "$fail"
}
# vim:set sw=4 sts=4 et:

View file

@ -1,165 +0,0 @@
#!/bin/sh
#
# Run a wrapped command with at least the requested locales available.
# Requires a dependency on locales | locales-all.
# The requested locales must be of the form foo_FOO.utf8, or special-cased
# in generate(), or listed in /usr/share/i18n/SUPPORTED, or specify the
# locale in the form locale=charset.
#
# Copyright 2016-2021 Simon McVittie
# Copyright 2017-2018 Collabora Ltd.
#
# SPDX-License-Identifier: MIT
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to
# deal in the Software without restriction, including without limitation the
# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
# sell copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
# IN THE SOFTWARE.
# Assume a Debian Policy §10.4-compatible shell like dash or bash (with the
# 'local' builtin)
# shellcheck disable=SC2039
set -eu
me="$(basename "$0")"
tempdir=
usage () {
local status="${1-2}"
if [ "$status" -ne 0 ]; then
exec >&2
fi
echo "Usage: $me [--generate LOCALE...] [--] COMMAND [ARGS...]"
exit "$status"
}
getopt_temp=help
getopt_temp="$getopt_temp,generate:"
getopt_temp="$(getopt -o '+' --long "$getopt_temp" -n "$0" -- "$@")"
eval set -- "$getopt_temp"
unset getopt_temp
generate () {
local locale="$1"
local charset=""
local source
local output
echo "$me: $locale..." >&2
case "$locale" in
(*=*)
source="${locale%=*}"
output="$source"
;;
(*.*)
source="${locale%.*}"
output="$source.$(
export LC_ALL=C
printf '%s' "${locale##*.}" | \
tr '[:upper:]' '[:lower:]' | \
tr -d -C '[:lower:][:digit:]'
)"
;;
(*)
source="${locale}"
output="${locale}"
esac
if [ -e "/usr/lib/locale/$output/LC_MESSAGES/SYS_LC_MESSAGES" ]; then
printf '\t%s\n' "Found in locales-all" >&2
return
fi
if ! [ -d /usr/share/i18n/charmaps ]; then
echo "$me: $locale not in locales-all and /usr/share/i18n/charmaps not found" >&2
return
fi
case "$locale" in
(*=*)
charset="${locale##*=}"
;;
(*.utf8 | *.UTF-8)
charset="UTF-8"
;;
(*.*)
charset="${locale##*.}"
;;
esac
if [ -z "$charset" ]; then
echo "$me: $locale charset not known" >&2
exit 1
fi
printf '\t%s\n' "Character set: $charset" >&2
printf '\t%s\n' "Source file: $source" >&2
if [ -z "$tempdir" ]; then
tempdir="$(mktemp -d)"
trap 'rm -fr "$tempdir"' EXIT
fi
printf '\t%s\n' "Output: $tempdir/$output" >&2
localedef -i "$source" -f "$charset" "$tempdir/$output"
}
while [ "$#" -gt 0 ]; do
case "$1" in
(--help)
usage 2
# not reached
;;
(--generate)
generate "$2"
shift 2
;;
(--)
shift
break
;;
(-*)
echo "$me: Unknown option: $1" >&2
usage 2
# not reached
;;
(*)
break
;;
esac
done
if [ -n "$tempdir" ]; then
export LOCPATH="$tempdir"
fi
"$@"
# vim:set sw=4 sts=4 et:

View file

@ -1,6 +0,0 @@
---
Name: GLib
Bug-Database: https://gitlab.gnome.org/GNOME/glib/issues/new
Repository: https://gitlab.gnome.org/GNOME/glib.git
Repository-Browse: https://gitlab.gnome.org/GNOME/glib/
Security-Contact: https://gitlab.gnome.org/GNOME/glib/-/blob/HEAD/SECURITY.md

7
debian/watch vendored
View file

@ -1,7 +0,0 @@
version=4
opts="searchmode=plain, uversionmangle=s/\.(alpha|beta|rc)/~$1/, downloadurlmangle=s|cache.json||" \
https://download.gnome.org/sources/glib/cache.json \
[\d.]+/glib-([\d.]+)@ARCHIVE_EXT@
#opts="mode=git,compression=xz" \
#https://gitlab.gnome.org/GNOME/glib.git \
#refs/tags/@ANY_VERSION@