Compare commits

..

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

2096 changed files with 1350753 additions and 1 deletions

11
.clang-format Normal file
View file

@ -0,0 +1,11 @@
# See https://wiki.apertis.org/Guidelines/Coding_conventions#Code_formatting
BasedOnStyle: GNU
AlwaysBreakAfterDefinitionReturnType: All
BreakBeforeBinaryOperators: None
BinPackParameters: false
SpaceAfterCStyleCast: true
# Our column limit is actually 80, but setting that results in clang-format
# making a lot of dubious hanging-indent choices; disable it and assume the
# developer will line wrap appropriately. clang-format will still check
# existing hanging indents.
ColumnLimit: 0

1
.dir-locals.el Normal file
View file

@ -0,0 +1 @@
((c-mode . ((indent-tabs-mode . nil)))))

17
.editorconfig Normal file
View file

@ -0,0 +1,17 @@
root = true
[*]
charset = utf-8
end_of_line = lf
[*.[ch]]
indent_size = 2
indent_style = space
insert_final_newline = true
# For the legacy tabs which still exist in the code:
tab_width = 8
[meson.build]
indent_size = 2
indent_style = space

40
AUTHORS Normal file
View file

@ -0,0 +1,40 @@
Below are just a few of the people who have contributed
to GLib. Please don't mail these people about problems you
have with GLib; see the README.md file for information about
filing bugs and submitting changes.
GLib-2.0 Team
-------------
Hans Breuer <hans@breuer.org>
Matthias Clasen <mclasen@redhat.com>
Tor Lillqvist <tml@iki.fi>
Tim Janik <timj@gtk.org>
Havoc Pennington <hp@redhat.com>
Ron Steinke <rsteinke@w-link.net>
Owen Taylor <otaylor@redhat.com>
Sebastian Wilhelmi <seppi@seppi.de>
GLib-1.2 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>
Original Authors
----------------
Peter Mattis <petm@xcf.berkeley.edu>
Spencer Kimball <spencer@xcf.berkeley.edu>
Josh MacDonald <jmacd@xcf.berkeley.edu>

274
CONTRIBUTING.md Normal file
View file

@ -0,0 +1,274 @@
# Contribution guidelines
Thank you for considering contributing to the GLib project!
These guidelines are meant for new contributors, regardless of their level
of proficiency; following them allows the core developers of the GLib project to
more effectively evaluate your contribution, and provide prompt feedback to
you. Additionally, by following these guidelines you clearly communicate
that you respect the time and effort that the people developing GLib put into
managing the project.
GLib is a complex free software utility library, and it would not exist without
contributions from the free and open source software community. There are
many things that we value:
- bug reporting and fixing
- documentation and examples
- tests
- testing and support for other platforms
- new features
Please, do not use the issue tracker for support questions. If you have
questions on how to use GLib effectively, you can use:
- the `#gtk` IRC channel on irc.gnome.org
- the [`glib` tag on GNOME's Discourse](https://discourse.gnome.org/tags/glib)
You can also look at the [`glib` tag on Stack
Overflow](https://stackoverflow.com/questions/tagged/glib).
The issue tracker is meant to be used for actionable issues only.
## How to report bugs
### Security issues
You should not open a new issue for security related questions.
When in doubt, send an email to the [security](mailto:security@gnome.org)
mailing list.
### Bug reports
If youre reporting a bug make sure to list:
0. which version of GLib are you using?
0. which operating system are you using?
0. the necessary steps to reproduce the issue
0. the expected outcome
0. a description of the behavior
0. a small, self-contained example exhibiting the behavior
If the issue includes a crash, you should also include:
0. the eventual warnings printed on the terminal
0. a backtrace, obtained with tools such as GDB or LLDB
If the issue includes a memory leak, you should also include:
0. a log of definite leaks from a tool such as [valgrinds
memcheck](http://valgrind.org/docs/manual/mc-manual.html)
For small issues, such as:
- spelling/grammar fixes in the documentation,
- typo correction,
- comment clean ups,
- changes to metadata files (CI, `.gitignore`),
- build system changes, or
- source tree clean ups and reorganizations;
or for self-contained bug fixes where you have implemented and tested a solution
already, you should directly open a merge request instead of filing a new issue.
### Features and enhancements
Feature discussion can be open ended and require high bandwidth channels; if
you are proposing a new feature on the issue tracker, make sure to make
an actionable proposal, and list:
0. what youre trying to achieve and the problem it solves
0. three (or more) existing pieces of software which would benefit from the
new feature
0. how the feature is implementable on platforms other than Linux
New APIs, in particular, should follow the rule of three, where there should
be three (or more) pieces of software which are ready to use the new APIs. This
allows us to check that the new APIs are usable in real-life code, and fit well
with related APIs. This reduces the chances of awkward or unusable APIs becoming
stable in GLib and having to be supported forever.
A common way to introduce new APIs or data types to GLib is to prototype them in
another code base for a while, to gain real-life experience with them before
they are imported into GLib and marked as stable.
Each feature should also come fully documented, and with tests which approach
full branch coverage of the new code. GLibs CI system generates code coverage
reports which are viewable for each merge request.
If proposing a large feature or change, its better to discuss it (on the
`#gtk` IRC channel or on [Discourse](https://discourse.gnome.org) before
putting time into writing an actionable issue — and certainly before putting
time into writing a merge request.
## Your first contribution
### Prerequisites
If you want to contribute to the GLib project, you will need to have the
development tools appropriate for your operating system, including:
- Python 3.x
- Meson
- Ninja
- Gettext (19.7 or newer)
- a [C99 compatible compiler](https://wiki.gnome.org/Projects/GLib/CompilerRequirements)
Up-to-date instructions about developing GNOME applications and libraries
can be found on [the GNOME Developer Center](https://developer.gnome.org).
The [GLib project uses GitLab](https://gitlab.gnome.org/GNOME/glib/) for code
hosting and for tracking issues. More information about using GitLab can be
found [on the GNOME wiki](https://wiki.gnome.org/GitLab).
### Getting started
You should start by forking the GLib repository from the GitLab web UI, and
cloning from your fork:
```sh
$ git clone https://gitlab.gnome.org/yourusername/glib.git
$ cd glib
```
**Note**: if you plan to push changes to back to the main repository and
have a GNOME account, you can skip the fork, and use the following instead:
```sh
$ git clone git@gitlab.gnome.org:GNOME/glib.git
$ cd glib
```
To compile the Git version of GLib on your system, you will need to
configure your build using Meson:
```sh
$ meson _builddir .
$ cd _builddir
$ ninja
```
Typically, you should work on your own branch:
```sh
$ git checkout -b your-branch
```
Once youve finished working on the bug fix or feature, push the branch
to the Git repository and open a new merge request, to let the GLib
core developers review your contribution.
### Code reviews
Each contribution is reviewed by the core developers of the GLib project.
The [CODEOWNERS](./docs/CODEOWNERS) document contains the list of core
contributors to GLib and the areas for which they are responsible; you
should ensure to receive their review and signoff on your changes.
It is our intention that every commit to GLib is reviewed by at least one other
person, including commits from core developers. We all make mistakes and can
always learn from each other, and code review allows that. It also reduces
[bus factor](https://en.wikipedia.org/wiki/Bus_factor) by spreading knowledge
of each commit between at least two people.
With each code review, we intend to:
0. Identify if this is a desirable change or new feature. Ideally for larger
features this will have been discussed (in an issue, on IRC, or on Discourse)
already, so that effort isnt wasted on putting together merge requests
which will be rejected.
0. Check the design of any new API.
0. Provide realistic estimates of how long a review might take, if it cant
happen immediately.
0. Ensure that all significant contributions of new code, or bug fixes, are
adequately tested, either through requiring tests to be submitted at the
same time, or as a follow-up.
0. Ensure that all new APIs are documented and have [introspection
annotations](https://wiki.gnome.org/Projects/GObjectIntrospection/Annotations).
0. Check that the contribution is split into logically separate commits, each
with a good commit message.
0. Encourage further high quality contributions.
0. Ensure code style and quality is upheld.
If a code review is stalled (due to not receiving comments for two or more
weeks; or due to a technical disagreement), please ping another GLib core
developer on the merge request, or on IRC, to ask for a second opinion.
### Commit messages
The expected format for git commit messages is as follows:
```plain
Short explanation of the commit
Longer explanation explaining exactly whats changed, whether any
external or private interfaces changed, what bugs were fixed (with bug
tracker reference if applicable) and so forth. Be concise but not too
brief.
Closes #1234
```
- Always add a brief description of the commit to the _first_ line of
the commit and terminate by two newlines (it will work without the
second newline, but that is not nice for the interfaces).
- First line (the brief description) must only be one sentence and
should start with a capital letter unless it starts with a lowercase
symbol or identifier. Dont use a trailing period either. Dont exceed
72 characters.
- The main description (the body) is normal prose and should use normal
punctuation and capital letters where appropriate. Consider the commit
message as an email sent to the developers (or yourself, six months
down the line) detailing **why** you changed something. Theres no need
to specify the **how**: the changes can be inlined.
- When committing code on behalf of others use the `--author` option, e.g.
`git commit -a --author "Joe Coder <joe@coder.org>"` and `--signoff`.
- If your commit is addressing an issue, use the
[GitLab syntax](https://docs.gitlab.com/ce/user/project/issues/automatic_issue_closing.html)
to automatically close the issue when merging the commit with the upstream
repository:
```plain
Closes #1234
Fixes #1234
Closes: https://gitlab.gnome.org/GNOME/glib/issues/1234
```
- If you have a merge request with multiple commits and none of them
completely fixes an issue, you should add a reference to the issue in
the commit message, e.g. `Bug: #1234`, and use the automatic issue
closing syntax in the description of the merge request.
### Merge access to the GLib repository
GLib is part of the GNOME infrastructure. At the current time, any
person with write access to the GNOME repository can merge merge requests to
GLib. This is a good thing, in that it allows maintainership to be delegated
and shared as needed. However, GLib is a fairly large and complicated package
that many other things depend on, and which has platform specific behavior — so
to avoid unnecessary breakage, and to take advantage of the knowledge about GLib
that has been built up over the years, wed like to ask people contributing to
GLib to follow a few rules:
0. Never push to the `main` branch, or any stable branches, directly; you
should always go through a merge request, to ensure that the code is
tested on the CI infrastructure at the very least. A merge request is
also the proper place to get a comprehensive code review from the core
developers of GLib.
0. Always get a code review, even for seemingly trivial changes.
0. Pay attention to the CI results. Merge requests cannot be merged until the
CI passes. If they consistently fail, either something is wrong with the
change, or the CI tests need fixing — in either case, please bring this to
the attention of a core developer rather than overriding the CI.
If you have been contributing to GLib for a while and you dont have commit
access to the repository, you may ask to obtain it following the [GNOME account
process](https://wiki.gnome.org/AccountsTeam/NewAccounts).

502
COPYING Normal file
View file

@ -0,0 +1,502 @@
GNU LESSER GENERAL PUBLIC LICENSE
Version 2.1, February 1999
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
[This is the first released version of the Lesser GPL. It also counts
as the successor of the GNU Library Public License, version 2, hence
the version number 2.1.]
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
Licenses are intended to guarantee your freedom to share and change
free software--to make sure the software is free for all its users.
This license, the Lesser General Public License, applies to some
specially designated software packages--typically libraries--of the
Free Software Foundation and other authors who decide to use it. You
can use it too, but we suggest you first think carefully about whether
this license or the ordinary General Public License is the better
strategy to use in any particular case, based on the explanations below.
When we speak of free software, we are referring to freedom of use,
not price. Our General Public Licenses are designed to make sure that
you have the freedom to distribute copies of free software (and charge
for this service if you wish); that you receive source code or can get
it if you want it; that you can change the software and use pieces of
it in new free programs; and that you are informed that you can do
these things.
To protect your rights, we need to make restrictions that forbid
distributors to deny you these rights or to ask you to surrender these
rights. These restrictions translate to certain responsibilities for
you if you distribute copies of the library or if you modify it.
For example, if you distribute copies of the library, whether gratis
or for a fee, you must give the recipients all the rights that we gave
you. You must make sure that they, too, receive or can get the source
code. If you link other code with the library, you must provide
complete object files to the recipients, so that they can relink them
with the library after making changes to the library and recompiling
it. And you must show them these terms so they know their rights.
We protect your rights with a two-step method: (1) we copyright the
library, and (2) we offer you this license, which gives you legal
permission to copy, distribute and/or modify the library.
To protect each distributor, we want to make it very clear that
there is no warranty for the free library. Also, if the library is
modified by someone else and passed on, the recipients should know
that what they have is not the original version, so that the original
author's reputation will not be affected by problems that might be
introduced by others.
Finally, software patents pose a constant threat to the existence of
any free program. We wish to make sure that a company cannot
effectively restrict the users of a free program by obtaining a
restrictive license from a patent holder. Therefore, we insist that
any patent license obtained for a version of the library must be
consistent with the full freedom of use specified in this license.
Most GNU software, including some libraries, is covered by the
ordinary GNU General Public License. This license, the GNU Lesser
General Public License, applies to certain designated libraries, and
is quite different from the ordinary General Public License. We use
this license for certain libraries in order to permit linking those
libraries into non-free programs.
When a program is linked with a library, whether statically or using
a shared library, the combination of the two is legally speaking a
combined work, a derivative of the original library. The ordinary
General Public License therefore permits such linking only if the
entire combination fits its criteria of freedom. The Lesser General
Public License permits more lax criteria for linking other code with
the library.
We call this license the "Lesser" General Public License because it
does Less to protect the user's freedom than the ordinary General
Public License. It also provides other free software developers Less
of an advantage over competing non-free programs. These disadvantages
are the reason we use the ordinary General Public License for many
libraries. However, the Lesser license provides advantages in certain
special circumstances.
For example, on rare occasions, there may be a special need to
encourage the widest possible use of a certain library, so that it becomes
a de-facto standard. To achieve this, non-free programs must be
allowed to use the library. A more frequent case is that a free
library does the same job as widely used non-free libraries. In this
case, there is little to gain by limiting the free library to free
software only, so we use the Lesser General Public License.
In other cases, permission to use a particular library in non-free
programs enables a greater number of people to use a large body of
free software. For example, permission to use the GNU C Library in
non-free programs enables many more people to use the whole GNU
operating system, as well as its variant, the GNU/Linux operating
system.
Although the Lesser General Public License is Less protective of the
users' freedom, it does ensure that the user of a program that is
linked with the Library has the freedom and the wherewithal to run
that program using a modified version of the Library.
The precise terms and conditions for copying, distribution and
modification follow. Pay close attention to the difference between a
"work based on the library" and a "work that uses the library". The
former contains code derived from the library, whereas the latter must
be combined with the library in order to run.
GNU LESSER GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License Agreement applies to any software library or other
program which contains a notice placed by the copyright holder or
other authorized party saying it may be distributed under the terms of
this Lesser General Public License (also called "this License").
Each licensee is addressed as "you".
A "library" means a collection of software functions and/or data
prepared so as to be conveniently linked with application programs
(which use some of those functions and data) to form executables.
The "Library", below, refers to any such software library or work
which has been distributed under these terms. A "work based on the
Library" means either the Library or any derivative work under
copyright law: that is to say, a work containing the Library or a
portion of it, either verbatim or with modifications and/or translated
straightforwardly into another language. (Hereinafter, translation is
included without limitation in the term "modification".)
"Source code" for a work means the preferred form of the work for
making modifications to it. For a library, complete source code means
all the source code for all modules it contains, plus any associated
interface definition files, plus the scripts used to control compilation
and installation of the library.
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running a program using the Library is not restricted, and output from
such a program is covered only if its contents constitute a work based
on the Library (independent of the use of the Library in a tool for
writing it). Whether that is true depends on what the Library does
and what the program that uses the Library does.
1. You may copy and distribute verbatim copies of the Library's
complete source code as you receive it, in any medium, provided that
you conspicuously and appropriately publish on each copy an
appropriate copyright notice and disclaimer of warranty; keep intact
all the notices that refer to this License and to the absence of any
warranty; and distribute a copy of this License along with the
Library.
You may charge a fee for the physical act of transferring a copy,
and you may at your option offer warranty protection in exchange for a
fee.
2. You may modify your copy or copies of the Library or any portion
of it, thus forming a work based on the Library, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) The modified work must itself be a software library.
b) You must cause the files modified to carry prominent notices
stating that you changed the files and the date of any change.
c) You must cause the whole of the work to be licensed at no
charge to all third parties under the terms of this License.
d) If a facility in the modified Library refers to a function or a
table of data to be supplied by an application program that uses
the facility, other than as an argument passed when the facility
is invoked, then you must make a good faith effort to ensure that,
in the event an application does not supply such function or
table, the facility still operates, and performs whatever part of
its purpose remains meaningful.
(For example, a function in a library to compute square roots has
a purpose that is entirely well-defined independent of the
application. Therefore, Subsection 2d requires that any
application-supplied function or table used by this function must
be optional: if the application does not supply it, the square
root function must still compute square roots.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Library,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Library, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote
it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Library.
In addition, mere aggregation of another work not based on the Library
with the Library (or with a work based on the Library) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may opt to apply the terms of the ordinary GNU General Public
License instead of this License to a given copy of the Library. To do
this, you must alter all the notices that refer to this License, so
that they refer to the ordinary GNU General Public License, version 2,
instead of to this License. (If a newer version than version 2 of the
ordinary GNU General Public License has appeared, then you can specify
that version instead if you wish.) Do not make any other change in
these notices.
Once this change is made in a given copy, it is irreversible for
that copy, so the ordinary GNU General Public License applies to all
subsequent copies and derivative works made from that copy.
This option is useful when you wish to copy part of the code of
the Library into a program that is not a library.
4. You may copy and distribute the Library (or a portion or
derivative of it, under Section 2) in object code or executable form
under the terms of Sections 1 and 2 above provided that you accompany
it with the complete corresponding machine-readable source code, which
must be distributed under the terms of Sections 1 and 2 above on a
medium customarily used for software interchange.
If distribution of object code is made by offering access to copy
from a designated place, then offering equivalent access to copy the
source code from the same place satisfies the requirement to
distribute the source code, even though third parties are not
compelled to copy the source along with the object code.
5. A program that contains no derivative of any portion of the
Library, but is designed to work with the Library by being compiled or
linked with it, is called a "work that uses the Library". Such a
work, in isolation, is not a derivative work of the Library, and
therefore falls outside the scope of this License.
However, linking a "work that uses the Library" with the Library
creates an executable that is a derivative of the Library (because it
contains portions of the Library), rather than a "work that uses the
library". The executable is therefore covered by this License.
Section 6 states terms for distribution of such executables.
When a "work that uses the Library" uses material from a header file
that is part of the Library, the object code for the work may be a
derivative work of the Library even though the source code is not.
Whether this is true is especially significant if the work can be
linked without the Library, or if the work is itself a library. The
threshold for this to be true is not precisely defined by law.
If such an object file uses only numerical parameters, data
structure layouts and accessors, and small macros and small inline
functions (ten lines or less in length), then the use of the object
file is unrestricted, regardless of whether it is legally a derivative
work. (Executables containing this object code plus portions of the
Library will still fall under Section 6.)
Otherwise, if the work is a derivative of the Library, you may
distribute the object code for the work under the terms of Section 6.
Any executables containing that work also fall under Section 6,
whether or not they are linked directly with the Library itself.
6. As an exception to the Sections above, you may also combine or
link a "work that uses the Library" with the Library to produce a
work containing portions of the Library, and distribute that work
under terms of your choice, provided that the terms permit
modification of the work for the customer's own use and reverse
engineering for debugging such modifications.
You must give prominent notice with each copy of the work that the
Library is used in it and that the Library and its use are covered by
this License. You must supply a copy of this License. If the work
during execution displays copyright notices, you must include the
copyright notice for the Library among them, as well as a reference
directing the user to the copy of this License. Also, you must do one
of these things:
a) Accompany the work with the complete corresponding
machine-readable source code for the Library including whatever
changes were used in the work (which must be distributed under
Sections 1 and 2 above); and, if the work is an executable linked
with the Library, with the complete machine-readable "work that
uses the Library", as object code and/or source code, so that the
user can modify the Library and then relink to produce a modified
executable containing the modified Library. (It is understood
that the user who changes the contents of definitions files in the
Library will not necessarily be able to recompile the application
to use the modified definitions.)
b) Use a suitable shared library mechanism for linking with the
Library. A suitable mechanism is one that (1) uses at run time a
copy of the library already present on the user's computer system,
rather than copying library functions into the executable, and (2)
will operate properly with a modified version of the library, if
the user installs one, as long as the modified version is
interface-compatible with the version that the work was made with.
c) Accompany the work with a written offer, valid for at
least three years, to give the same user the materials
specified in Subsection 6a, above, for a charge no more
than the cost of performing this distribution.
d) If distribution of the work is made by offering access to copy
from a designated place, offer equivalent access to copy the above
specified materials from the same place.
e) Verify that the user has already received a copy of these
materials or that you have already sent this user a copy.
For an executable, the required form of the "work that uses the
Library" must include any data and utility programs needed for
reproducing the executable from it. However, as a special exception,
the materials to be distributed need not include anything that is
normally distributed (in either source or binary form) with the major
components (compiler, kernel, and so on) of the operating system on
which the executable runs, unless that component itself accompanies
the executable.
It may happen that this requirement contradicts the license
restrictions of other proprietary libraries that do not normally
accompany the operating system. Such a contradiction means you cannot
use both them and the Library together in an executable that you
distribute.
7. You may place library facilities that are a work based on the
Library side-by-side in a single library together with other library
facilities not covered by this License, and distribute such a combined
library, provided that the separate distribution of the work based on
the Library and of the other library facilities is otherwise
permitted, and provided that you do these two things:
a) Accompany the combined library with a copy of the same work
based on the Library, uncombined with any other library
facilities. This must be distributed under the terms of the
Sections above.
b) Give prominent notice with the combined library of the fact
that part of it is a work based on the Library, and explaining
where to find the accompanying uncombined form of the same work.
8. You may not copy, modify, sublicense, link with, or distribute
the Library except as expressly provided under this License. Any
attempt otherwise to copy, modify, sublicense, link with, or
distribute the Library is void, and will automatically terminate your
rights under this License. However, parties who have received copies,
or rights, from you under this License will not have their licenses
terminated so long as such parties remain in full compliance.
9. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Library or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Library (or any work based on the
Library), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Library or works based on it.
10. Each time you redistribute the Library (or any work based on the
Library), the recipient automatically receives a license from the
original licensor to copy, distribute, link with or modify the Library
subject to these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties with
this License.
11. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Library at all. For example, if a patent
license would not permit royalty-free redistribution of the Library by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Library.
If any portion of this section is held invalid or unenforceable under any
particular circumstance, the balance of the section is intended to apply,
and the section as a whole is intended to apply in other circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
12. If the distribution and/or use of the Library is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Library under this License may add
an explicit geographical distribution limitation excluding those countries,
so that distribution is permitted only in or among countries not thus
excluded. In such case, this License incorporates the limitation as if
written in the body of this License.
13. The Free Software Foundation may publish revised and/or new
versions of the Lesser General Public License from time to time.
Such new versions will be similar in spirit to the present version,
but may differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the Library
specifies a version number of this License which applies to it and
"any later version", you have the option of following the terms and
conditions either of that version or of any later version published by
the Free Software Foundation. If the Library does not specify a
license version number, you may choose any version ever published by
the Free Software Foundation.
14. If you wish to incorporate parts of the Library into other free
programs whose distribution conditions are incompatible with these,
write to the author to ask for permission. For software which is
copyrighted by the Free Software Foundation, write to the Free
Software Foundation; we sometimes make exceptions for this. Our
decision will be guided by the two goals of preserving the free status
of all derivatives of our free software and of promoting the sharing
and reuse of software generally.
NO WARRANTY
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Libraries
If you develop a new library, and you want it to be of the greatest
possible use to the public, we recommend making it free software that
everyone can redistribute and change. You can do so by permitting
redistribution under these terms (or, alternatively, under the terms of the
ordinary General Public License).
To apply these terms, attach the following notices to the library. It is
safest to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least the
"copyright" line and a pointer to where the full notice is found.
<one line to give the library's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This library 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.1 of the License, or (at your option) any later version.
This library 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 library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Also add information on how to contact you by electronic and paper mail.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the library, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the
library `Frob' (a library for tweaking knobs) written by James Random Hacker.
<signature of Ty Coon>, 1 April 1990
Ty Coon, President of Vice
That's all there is to it!

17
HACKING Normal file
View file

@ -0,0 +1,17 @@
If you want to hack on the GLib project, you'll need to have the
following packages installed:
- Meson 0.48.0
- GNU gettext 0.10.40
- pkg-config 0.16
- gtk-doc
- libffi 3.0.0
To compile a Git version of glib on your system, you will need to take
several steps to setup the tree for compilation. You can do all these
steps at once by running:
checkout/glib# meson _build
For information about submitting patches see the CONTRIBUTING.md file. For
information about major design decisions, see the README.rationale file.

125
INSTALL.in Normal file
View file

@ -0,0 +1,125 @@
Simple install procedure
========================
% tar xf glib-@GLIB_VERSION@.tar.gz # unpack the sources
% cd glib-@GLIB_VERSION@ # change to the toplevel directory
% meson _build # configure the build
% ninja -C _build # build GLib
[ Become root if necessary ]
% ninja -C _build install # install GLib
Requirements
============
GLib requires a C90-compliant (but not necessarily C99-compliant) C
compiler and libc. On UNIX-like systems, it also assumes compliance
with at least the original 1990 version of POSIX.
GLib-2.0 requires pkg-config, which is tool for tracking the
compilation flags needed for libraries. (For each library, a small .pc
text file is installed in a standard location that contains the
compilation flags needed for that library along with version number
information.) Information about pkg-config can be found at:
http://www.freedesktop.org/software/pkgconfig/
Meson (http://mesonbuild.com/) is also required.
In order to implement conversions between character sets,
GLib requires an implementation of the standard iconv() routine.
Most modern systems will have a suitable implementation, however
many older systems lack an iconv() implementation. On such systems,
you must install the libiconv library. This can be found at:
http://www.gnu.org/software/libiconv/
If your system has an iconv implementation but you want to use
libiconv instead, you can pass the --with-libiconv option to
configure. This forces libiconv to be used.
Note that if you have libiconv installed in your default include
search path (for instance, in /usr/local/), but don't enable
it, you will get an error while compiling GLib because the
iconv.h that libiconv installs hides the system iconv.
If you are using the native iconv implementation on Solaris
instead of libiconv, you'll need to make sure that you have
the converters between locale encodings and UTF-8 installed.
At a minimum you'll need the SUNWuiu8 package. You probably
should also install the SUNWciu8, SUNWhiu8, SUNWjiu8, and
SUNWkiu8 packages.
The native iconv on Compaq Tru64 doesn't contain support for
UTF-8, so you'll need to use GNU libiconv instead. (When
using GNU libiconv for GLib, you'll need to use GNU libiconv
for GNU gettext as well.) This probably applies to related
operating systems as well.
Finally, for message catalog handling, GLib requires an implementation
of gettext(). If your system doesn't provide this functionality,
you should use the libintl library from the GNU gettext package,
available from:
http://www.gnu.org/software/gettext/
Support for extended attributes and SELinux in GIO requires
libattr and libselinux.
Some of the mimetype-related functionality in GIO requires the
update-mime-database and update-desktop-database utilities, which
are part of shared-mime-info and desktop-file-utils, respectively.
GObject uses libffi to implement generic marshalling functionality.
The Nitty-Gritty
================
Complete information about installing GLib can be found
in the file:
docs/reference/glib/html/glib-building.html
Or online at:
https://developer.gnome.org/glib/stable/glib-building.html
Installation directories
========================
The location of the installed files is determined by the --prefix
and --exec-prefix options given to configure. There are also more
detailed flags to control individual directories. However, the
use of these flags is not tested.
One particular detail to note, is that the architecture-dependent
include file glibconfig.h is installed in:
$libdir/glib-2.0/include/
.pc files for the various libraries are installed in
$libdir/pkgconfig to provide information when compiling
other packages that depend on GLib. If you set PKG_CONFIG_PATH
so that it points to this directory, then you can get the
correct include flags and library flags for compiling a GLib
application with:
pkg-config --cflags glib-2.0
pkg-config --libs glib-2.0
This is the only supported way of determining the include and library flags
for building against GLib.
Cross-compiling GLib
====================
Information about cross-compilation of GLib can be found
in the file:
docs/reference/glib/html/glib-cross-compiling.html
Or online at:
https://developer.gnome.org/glib/stable/glib-cross-compiling.html

14420
NEWS Normal file

File diff suppressed because it is too large Load diff

211
NEWS.pre-1-3 Normal file
View file

@ -0,0 +1,211 @@
Overview of Changes in GLib 1.2.1:
* g_realloc() fix for SunOS (please report further problems).
* Continued the never ending fix vendetta regarding getpwuid(),
this time AIX has been the culprit.
* Upgrade to libtool 1.2f
* Miscellaneous other buglets fixed.
What's new in GLib 1.2.0 (since GLib 1.0.x):
* GLib is distributed seperatedly from Gtk+
* Win32 Portability
* Threading support
* GModule mechanism (implemented in an extra library) which wraps dynamic
object code loading facilities in a portable manner
* GIOChannel structure to encapsulate the IPC mechanism
* GQuarks and datasets
* GRelations for n-way mapping of certain data
* An n-way tree implementation
* GDate functionality for calendar date manipulations
* GAllocator type and associated functions
* Added generic callback maintenance functions (ghook)
* Generic functions for TAB completions
* Endian defines (G_*_ENDIAN)
* g_log() mechanism for logging of messages at different log levels
* Generic main-loop mechanism
* New glib-config helper script
* Many more API extensions
Overview of Changes in GLib 1.1.16:
* Allocate smaller pools of memory for glists, gslists, gnodes
* Bug Fixes
Overview of Changes in GLib 1.1.15:
* HPUX 11 thread system detection should now work
* Release the main loop lock around calls to prepare() and
check() so it is not held over user code
* A few Win32 fixups
Overview of Changes in GLib 1.1.14:
* Check for dlsym() in system libraries and -dl
* FreeBSD portability fixes
* Random bug fixes and autoconf/automake changes
Overview of Changes in GLib 1.1.13:
* Removed alloca() based function and macro variants again.
* Improved thread related configure tests.
* GSource destruction fixups.
* Fixed up idle function removal based on user_data pointer.
* Advanced Win32 portability.
* Enforced GSource's check(), prepare() and dispatch() constrains,
loop recursions may only happen from dispatch(), and check() as well
as prepare() are called while the main_loop lock is being held.
* GLib development now requires GNU autoconf 2.13, GNU automake 1.4
and GNU libtool 1.2d.
* Lots of random portability and bug fixes.
Overview of Changes in GLib 1.1.12:
* Added alloca functions/macros: g_strdup_a, g_strconcat3_a, g_alloca,
g_new_a, g_new0_a
* New tests structure. Type 'make check' on your system to run them.
* Avoid unnecessary extra hook referencing in g_hook_list_marshal
Overview of Changes in GLib 1.1.11:
* provide defaults for POLL sysdefs
* g_main_is_running: new function to check whether a main loop has been quitted
* a few other enhancement/fixes
Overview of Changes in GLib 1.1.9:
* Check for pthread_attr_init in all cases, Digital Unix 4 requires this
* For G_LOCK_DECLARE_*, if !G_THREADS_ENABLED, eat trailing semicolon better
* Changed g_main_poll_(add|remove) to g_main_(add|remove)_poll
Overview of Changes in GLib 1.1.8:
* Added threading support
- The ability to specify a set of functions to be used for
locking at runtime.
- Default implementations of locking functions for pthreads,
Solaris threads, and (experimentally) NSPR.
- All static variables should now properly locked.
- Enhancements to the generic main-loop mechanism to be thread-safe.
(It is used for the main-loop in GTK+ as of GTK+-1.1.8)
* Portability fixes.
Overview of Changes in GLib 1.1.7:
* Removed multiple define from glibconfig.h
Overview of Changes in GLib 1.1.6:
* New GDate functionality for calendar date manipulations (g_date_*)
* New GAllocator type and associated functions
* New functions g_slist_copy and g_list_copy to duplicate a list with all
its data pointers.
* New function g_array_insert_vals and new macro g_array_insert_val to
insert elements at an arbitrary index
* GAllocators used for glist, gslist, gnode node allocations
* Incremental freezing in ghash
* New function g_hook_list_marshal_check to eventually destroy hooks after
they got marshalled
* Revised GIOChannel to provide generic virtual-function based interface
* Added generic main-loop abstraction
* Removed GListAllocator type and its g_*_allocator_*() function variants
* Bug fixes
Overview of Changes in GLib 1.1.5:
* Win32 portability
* GIOChannel structure to encapsulate the IPC mechanism
* Reimplemented endian stuff, using inline asm for x86
* New functions:
- g_strescape: escapes backslashes
- g_path_is_absolute and g_path_skip_root
- g_getenv: expands environment variables that contain references
to other environment variables
- g_scanner_sync_file_offset: rewind the filedescriptor to the current
buffer position and blow the file read ahead buffer
- g_array_remove_index: remove an entry, preserving the order
- g_array_remove_index_fast: remove an entry, order might be distorted
- g_ptr_array_remove: remove an entry, preserving the order
- g_ptr_array_remove_fast: remove an entry, order might be distorted
- g_byte_array_remove_index: wrapper for g_array_remove_index
- g_byte_array_remove_index_fast: wrapper for g_array_remove_index_fast
- g_strncasecmp: modeled closely after g_strcasecmp
- g_list_sort, g_slist_sort: to merge sort GLists and GSLists
* New macros:
- G_DIR_SEPARATOR, G_DIR_SEPARATOR_S: platform-dependant file name
syntax elements
- G_SEARCHPATH_SEPARATOR, G_SEARCHPATH_SEPARATOR_S: platform-dependant
search path syntax conventions
- G_STRUCT_OFFSET, G_STRUCT_MEMBER_P, G_STRUCT_MEMBER: for handling
structure fields through their offsets
* Removed G_ENUM, G_FLAGS, G_NV, and G_SV macros
* Bug fixes
Overview of Changes in GLib 1.1.4:
* Added generic callback maintenance functions (ghook)
* New endian defines (G_*_ENDIAN)
* New string join/split/free routines
* Fixes
Overview of Changes in GLib 1.1.3:
* New GModule mechanism (implemented in an extra library) which wraps dynamic
object code loading facilities in a portable manner.
* glib-config features extra "glib" (old behaviour remains) and "gmodule"
(add libgmodule.so to the --libs output) arguments now. this can also
be specified as fourth argument to the AM_PATH_GLIB() macro.
* Overhaul of the `inline' autoconfiguration stuff, so inlining should be
sufficiently supported on all systems that allow inlining now.
* New g_log() mechanism for logging of messages at different log levels,
associated with certain log domains (define -DG_LOG_DOMAIN for your library).
* New inline functions for bit masks tests.
* GNode macros (and functions) now return the newly allocated node.
* New macro G_VA_COPY() to work around va_list copying oddities on some
platforms. the non-static g_vsprintf() function vanished in favour of
a publically exported g_strdup_vprintf().
People that used the former g_vsprintf() would definitely want to read the
associated ChangeLog entries (grep for printf).
* New utility functions:
g_strndup(), g_on_error_query(), g_on_error_stack_trace(), g_strdup_printf(),
g_strdup_vprintf(), g_printf_string_upper_bound(), g_spaced_primes_closest(),
g_strnfill(), g_memdup().
* Overhaul of the array implementations, this contains some source incompatible
changes. Again, the ChangeLog is much more informative (grep for garray.c).
* The internals of the g_dataset mechanism are now exported through the
new g_datalist_* API (this is also the underlying implementation for the
keyed data of GtkObjects).
* New function g_atexit(), use of the ATEXIT() macro is discouraged.
* Better configure checks for ansi compliance.
* Libtool update to version 1.2b.
* Lotsa bug fixes and cleanups as always ;)
Overview of Changes in GLib 1.1.2:
* Fixed packaging mistake which occured in 1.1.1
* fix 64-bitness in g_prints in glibtest
What is new in GLib 1.1.1:
* An n-way tree implementation is provided now, based on the GNode structure.
* Bugfix for pointer arrays.
What is new in GLib 1.1.0:
* GLib is distributed seperatedly from Gtk+ now and uses a sophisticated
shared library versioning scheme to deal with interface and binary
incompatibilities.
* There is a glib-config helper script installed now.
* Fixups all over the place.
* gboolean is now a gint, not a gchar anymore.
* API extensions for GList and GSList.
* New g_str*() functions for simple string handling.
* GScanner extensions for scope, warning and error handling.
* Minor performance improvements for GMemChunks.
* Implementations of GQuarks and datasets (similar to GtkObjects data
mechansim, but works for generic memory locations).
* More convenience macros for GNU C function arguments.
* Const correction all over the place, including a new pointer type
gconstpointer.
* Generic functions for TAB completions.
* GRelations for n-way mapping of certain data.

1
README Normal file
View file

@ -0,0 +1 @@
See README.md

93
README.md Normal file
View file

@ -0,0 +1,93 @@
# GLib
GLib is the low-level core library that forms the basis for projects such
as GTK and GNOME. It provides data structure handling for C, portability
wrappers, and interfaces for such runtime functionality as an event loop,
threads, dynamic loading, and an object system.
The official download locations are:
<https://download.gnome.org/sources/glib>
The official web site is:
<https://www.gtk.org/>
## Installation
See the file '[INSTALL.in](INSTALL.in)'
## Supported versions
Only the most recent unstable and stable release series are supported. All
older versions are not supported upstream and may contain bugs, some of
which may be exploitable security vulnerabilities.
See [SECURITY.md](SECURITY.md) for more details.
## Documentation
API documentation is available online for GLib for the:
* [GLib](https://docs.gtk.org/glib/)
* [GObject](https://docs.gtk.org/gobject/)
* [GModule](https://docs.gtk.org/gmodule/)
* [GIO](https://docs.gtk.org/gio/)
## Discussion
If you have a question about how to use GLib, seek help on [GNOMEs Discourse
instance](https://discourse.gnome.org/tags/glib). Alternatively, ask a question
on [StackOverflow and tag it `glib`](https://stackoverflow.com/questions/tagged/glib).
## Reporting bugs
Bugs should be [reported to the GNOME issue tracking system](https://gitlab.gnome.org/GNOME/glib/issues/new).
You will need to create an account for yourself. You may also submit bugs by
e-mail (without an account) by e-mailing <incoming+gnome-glib-658-issue-@gitlab.gnome.org>,
but this will give you a degraded experience.
Bugs are for reporting problems in GLib itself, not for asking questions about
how to use it. To ask questions, use one of our [discussion forums](#discussion).
In bug reports please include:
* Information about your system. For instance:
* What operating system and version
* For Linux, what version of the C library
* And anything else you think is relevant.
* How to reproduce the bug.
* If you can reproduce it with one of the test programs that are built
in the `tests/` subdirectory, that will be most convenient. Otherwise,
please include a short test program that exhibits the behavior.
As a last resort, you can also provide a pointer to a larger piece
of software that can be downloaded.
* If the bug was a crash, the exact text that was printed out
when the crash occurred.
* Further information such as stack traces may be useful, but
is not necessary.
## Contributing to GLib
Please follow the [contribution guide](./CONTRIBUTING.md) to know how to
start contributing to GLib.
Patches should be [submitted as merge requests](https://gitlab.gnome.org/GNOME/glib/-/merge_requests/new)
to gitlab.gnome.org. If the patch fixes an existing issue, please refer to the
issue in your commit message with the following notation (for issue 123):
```
Closes: #123
```
Otherwise, create a new merge request that introduces the change. Filing a
separate issue is not required.
## Default branch renamed to `main`
The default development branch of GLib has been renamed to `main`. To update
your local checkout, use:
```sh
git checkout master
git branch -m master main
git fetch
git branch --unset-upstream
git branch -u origin/main
git symbolic-ref refs/remotes/origin/HEAD refs/remotes/origin/main
```

16
README.rationale Normal file
View file

@ -0,0 +1,16 @@
This file documents various major decisions which affect GLib development,
giving a brief rationale of each decision, plus a link to further discussion.
* Compiler attributes: https://bugzilla.gnome.org/show_bug.cgi?id=113075#c46
GLib uses GIR annotations instead of compiler attributes. They are tidier,
already supported by GLib and GNOME tools, and accomplish the same task as
compiler attributes. GLib does not provide macros for attributes like
nonnull because it would not use them.
* Main loop API:
The ID-based mainloop APIs (g_idle_add, g_timeout_add, etc) are considered
legacy, and new features (such as g_source_set_static_name) will only be
added to the explicit GSource APIs.

1
README.win32 Normal file
View file

@ -0,0 +1 @@
See README.win32.md

169
README.win32.md Normal file
View file

@ -0,0 +1,169 @@
Chun-wei Fan `<fanc999@yahoo.com.tw>`
Philip Withnall `<withnall@endlessm.com>`
Nirbheek Chauhan `<nirbheek@centricular.com>`
This document was last updated in 2019. You're reading this in the future, and
lots of information might be misleading or outdated in your age. You have been
warned.
# General
For prebuilt binaries (DLLs and EXEs) and developer packages (headers,
import libraries) of GLib, Pango, GTK+ etc for Windows, go to
https://www.gtk.org/download/windows.php . They are for "native"
Windows meaning they use the Win32 API and Microsoft C runtime library
only. No POSIX (Unix) emulation layer like Cygwin is involved.
To build GLib on Win32, you can use either GCC ("MinGW") or the Microsoft
Visual Studio toolchain. For the latter, Visual Studio 2015 and later are
recommended. For older Visual Studio versions, see below.
You can also cross-compile GLib for Windows from Linux using the
cross-compiling mingw packages for your distro.
Note that to just *use* GLib on Windows, there is no need to build it
yourself.
On Windows setting up a correct build environment is very similar to typing
`meson; ninja` like on Linux.
The following preprocessor macros are to be used for conditional
compilation related to Win32 in GLib-using code:
- `G_OS_WIN32` is defined when compiling for native Win32, without
any POSIX emulation, other than to the extent provided by the
bundled Microsoft C library.
- `G_WITH_CYGWIN` is defined if compiling for the Cygwin
environment. Note that `G_OS_WIN32` is *not* defined in that case, as
Cygwin is supposed to behave like Unix. `G_OS_UNIX` *is* defined by a GLib
for Cygwin.
- `G_PLATFORM_WIN32` is defined when either `G_OS_WIN32` or `G_WITH_CYGWIN`
is defined.
These macros are defined in `glibconfig.h`, and are thus available in
all source files that include `<glib.h>`.
Additionally, there are the compiler-specific macros:
- `__GNUC__` is defined when using GCC or Clang
- `__clang__` is defined when using Clang or Clang-CL
- `_MSC_VER` is defined when using MSVC or Clang-CL
`G_OS_WIN32` implies using the Microsoft C runtime, which used to be
`msvcrt.dll` and is now the [Universal CRT](https://docs.microsoft.com/en-us/cpp/c-runtime-library/crt-library-features?view=vs-2015)
when building with Visual Studio. When using the MinGW-GCC toolchain, the CRT
in use depends on the settings used while the toolchain was built. We highly
recommend [using the Universal CRT when building with
MinGW](https://mingwpy.github.io/ucrt.html) too.
GLib is not actively tested with the static versions of the UCRT, but if you
need to use those, patches are welcome.
# Building software that use GLib or GTK+
Building software that just *uses* GLib or GTK+ also require to have
the right compiler set up the right way. If you intend to use MinGW-GCC,
follow the relevant instructions below in that case, too.
You should link to GLib using the `-mms-bitfields` GCC flag. This flag means
that the struct layout rules are identical to those used by MSVC. This is
essential if the same DLLs are to be usable both from gcc- and MSVC-compiled
code.
## Cross-CRT issues
You should take care that the DLLs that your code links to are using the same
C runtime library. Not doing so can and likely will lead to panics and crashes
**unless** you're very careful while passing objects allocated by a library
linked with one CRT to a library linked to another CRT, or (more commonly) not
doing that at all.
If you *do* pass CRT objects across CRT boundaries, do not file any issues
about whatever happens next.
To give an example, opening a `FILE` handle created by one CRT cannot be
understood by any other CRT, and will lead to an access violation. You also
cannot allocate memory in one CRT and free it using another.
There are [many other cases where you must not allow objects to cross CRT boundaries](https://docs.microsoft.com/en-us/cpp/c-runtime-library/potential-errors-passing-crt-objects-across-dll-boundaries?view=vs-2019),
but in theory if you're **very very** careful, you can make things work. Again,
please do not come to us for help if you choose to do this.
# Building GLib
You can build GLib with MinGW-GCC, MSVC, or (experimentally) with Clang-CL.
For all compilers, you will need the following:
- Install Python 3.6.x or newer, either 32-bit or 64-bit. We recommend enabling
the option to add it to your `PATH`.
- [Install Meson](https://mesonbuild.com/Getting-meson.html)
- Install the [Ninja build tool](https://github.com/ninja-build/ninja/releases), which can also be
installed with `pip3`. You can skip this step if you want to generate Visual
Studio project files.
- [git for Windows](https://gitforwindows.org/) is required, since Meson makes
use of git to download dependencies using subprojects.
## Building with MinGW-GCC
Open your MSYS or [MSYS2](https://www.msys2.org/) shell where you have the
MinGW-GCC toolchain installed, and build GLib [like any other Meson
project](https://mesonbuild.com/Quick-guide.html#compiling-a-meson-project).
## Building with Visual Studio 2015 or newer
Meson is now the only supported method of building GLib using Visual Studio.
To do a build using Meson, do the following:
- Open a Visual Studio (or SDK) command prompt that matches the Visual Studio
version and build platform (Win32/x86, x64, etc.) that will be used in all
the following steps.
- Create an empty directory/folder for the build inside your GLib sources
directory, say, `_builddir`, and `cd` into it.
- Set up the build using Meson:
```cmd
> meson .. --buildtype=<release|debug|debugoptimized> --prefix=<path> [--backend=vs]
```
Please see [the Meson docs](https://mesonbuild.com/Builtin-options.html#core-options)
for an explanation for `--buildtype`.
The path passed for `--prefix` need not to be on the same drive as where the
build is carried out, but it is recommended to use forward slashes for this
path. The `--backend=vs` option can be used if the Visual Studio project
generator is preferred over using Ninja.
- Build, test and install the build:
Run `ninja` to build, `meson test` to test and `meson install` to install the
build. If you used `--backend=vs`, instead of running `ninja`, you need to
use `msbuild` or you can open the generated solution in Visual Studio.
## Building with old versions of Visual Studio
The steps are the same as above, with the following notes about issues that you might face.
### C4819 build errors
If you are building GLib-based libraries or applications, or GLib itself
and you see a `C4819` error (or warning, before `C4819` is treated as an error
in `msvc_recommended_pragmas.h`), please be advised that this error/warning should
not be disregarded, as this likely means portions of the build are not being
done correctly, as this is an issue of Visual Studio running on CJK (East Asian)
locales. This is an issue that also affects builds of other projects, such as
QT, Firefox, LibreOffice/OpenOffice, Pango and GTK, along with many other projects.
To overcome this problem, please set your system's locale setting for non-Unicode to
English (United States), reboot, and restart the build, and the code should build
normally.
### Support for pre-2012 Visual Studio
This release of GLib requires at least the Windows 8 SDK in order to be built
successfully using Visual Studio, which means that it is no longer supported to
build GLib with Visual Studio 2008 nor 2010. People that still need to use
Visual Studio 2008 or 2010 should continue to use glib-2.66.x.

78
SECURITY.md Normal file
View file

@ -0,0 +1,78 @@
# Security policy for GLib
* [Supported Versions](#Supported-Versions)
* [Reporting a Vulnerability](#Reporting-a-Vulnerability)
* [Security Announcements](#Security-Announcements)
* [Acknowledgements](#Acknowledgements)
## Supported Versions
Upstream GLib only supports the most recent stable release series, and the
current development release series. Any older stable release series are no
longer supported, although they may still receive backported security updates
in long-term support distributions. Such support is up to the distributions,
though.
Under GLibs versioning scheme, stable release series have an *even* minor
component (for example, 2.66.0, 2.66.1, 2.68.3), and development release series
have an *odd* minor component (2.67.1, 2.69.0).
## Signed Releases
The git tags for all releases ≥2.58.0 are signed by a maintainer using
[git-evtag](https://github.com/cgwalters/git-evtag). The maintainer will use
their personal GPG key; there is currently not necessarily a formal chain of
trust for these keys. Please [create an issue](https://gitlab.gnome.org/GNOME/glib/-/issues/new)
if you would like to work on improving this.
Unsigned releases ≥2.58.0 should not be trusted. Releases prior to 2.58.0 were
not signed.
## Reporting a Vulnerability
If you think you've identified a security issue in GLib, GObject or GIO, please
**do not** report the issue publicly via a mailing list, IRC, a public issue on
the GitLab issue tracker, a merge request, or any other public venue.
Instead, report a
[*confidential* issue in the GitLab issue tracker](https://gitlab.gnome.org/GNOME/glib/-/issues/new?issue[confidential]=1),
with the “This issue is confidential” box checked. Please include as many
details as possible, including a minimal reproducible example of the issue, and
an idea of how exploitable/severe you think it is.
**Do not** provide a merge request to fix the issue, as there is currently no
way to make confidential merge requests on gitlab.gnome.org. If you have patches
which fix the security issue, please attach them to your confidential issue as
patch files.
Confidential issues are only visible to the reporter and the GLib maintainers.
As per the [GNOME security policy](https://security.gnome.org/), the next steps
are then:
* The report is triaged.
* Code is audited to find any potential similar problems.
* If it is determined, in consultation with the submitter, that a CVE is
required, the submitter obtains one via [cveform.mitre.org](https://cveform.mitre.org/).
* The fix is prepared for the development branch, and for the most recent
stable branch.
* The fix is submitted to the public repository.
* On the day the issue and fix are made public, an announcement is made on the
[public channels listed below](#Security-Announcements).
* A new release containing the fix is issued.
## Security Announcements
Security announcements are made publicly via the
[`distributor` tag on discourse.gnome.org](https://discourse.gnome.org/tag/distributor)
and cross-posted to the
[distributor-list](https://mail.gnome.org/mailman/listinfo/distributor-list).
Announcements for security issues with wide applicability or high impact may
additionally be made via
[oss-security@lists.openwall.com](https://www.openwall.com/lists/oss-security/).
## Acknowledgements
This text was partially based on the
[github.com/containers security policy](https://github.com/containers/common/blob/HEAD/SECURITY.md),
and partially based on the [flatpak security policy](https://github.com/flatpak/flatpak/blob/HEAD/SECURITY.md).

23
check-abis.sh Executable file
View file

@ -0,0 +1,23 @@
#!/bin/sh -e
list_leaked_symbols () {
nm -D "$1" | grep ' T ' | cut -f 3 -d ' ' | grep -E -v "$2"
}
check_symbols () {
if [ "$(list_leaked_symbols "$1" "$2" | wc -l)" -ne 0 ]; then
echo File "$1" possibly leaking symbols:
list_leaked_symbols "$1" "$2"
exit 1
fi
}
allowed="^_init$|^_fini$|^_ftext$|^g_"
allowed_in_libglib="${allowed}|^glib__private__$|^glib_gettext$|^glib_pgettext$|^glib_check_version$"
allowed_in_libgthread='^_init$|^_fini$|^_ftext$|^g_thread_init$|^g_thread_init_with_errorcheck_mutexes$'
check_symbols glib/.libs/libglib-2.0.so "$allowed_in_libglib"
check_symbols gthread/.libs/libgthread-2.0.so "$allowed_in_libgthread"
for file in gmodule/.libs/libgmodule-2.0.so gobject/.libs/libgobject-2.0.so gio/.libs/libgio-2.0.so; do
check_symbols "$file" "$allowed"
done

166
clang-format-diff.py Executable file
View file

@ -0,0 +1,166 @@
#!/usr/bin/env python3
#
# === clang-format-diff.py - ClangFormat Diff Reformatter ---*- python -*-=== #
#
# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
# See https://llvm.org/LICENSE.txt for license information.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
#
# ===---------------------------------------------------------------------=== #
"""
This script reads input from a unified diff and reformats all the changed
lines. This is useful to reformat all the lines touched by a specific patch.
Example usage for git/svn users:
git diff -U0 --no-color HEAD^ | clang-format-diff.py -p1 -i
svn diff --diff-cmd=diff -x-U0 | clang-format-diff.py -i
"""
from __future__ import absolute_import, division, print_function
import argparse
import difflib
import re
import subprocess
import sys
if sys.version_info.major >= 3:
from io import StringIO
else:
from io import BytesIO as StringIO
def main():
parser = argparse.ArgumentParser(
description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter
)
parser.add_argument(
"-i",
action="store_true",
default=False,
help="apply edits to files instead of displaying a " "diff",
)
parser.add_argument(
"-p",
metavar="NUM",
default=0,
help="strip the smallest prefix containing P slashes",
)
parser.add_argument(
"-regex",
metavar="PATTERN",
default=None,
help="custom pattern selecting file paths to reformat "
"(case sensitive, overrides -iregex)",
)
parser.add_argument(
"-iregex",
metavar="PATTERN",
default=r".*\.(cpp|cc|c\+\+|cxx|c|cl|h|hh|hpp|m|mm|inc"
r"|js|ts|proto|protodevel|java|cs)",
help="custom pattern selecting file paths to reformat "
"(case insensitive, overridden by -regex)",
)
parser.add_argument(
"-sort-includes",
action="store_true",
default=False,
help="let clang-format sort include blocks",
)
parser.add_argument(
"-v",
"--verbose",
action="store_true",
help="be more verbose, ineffective without -i",
)
parser.add_argument(
"-style",
help="formatting style to apply (LLVM, Google, " "Chromium, Mozilla, WebKit)",
)
parser.add_argument(
"-binary",
default="clang-format",
help="location of binary to use for clang-format",
)
args = parser.parse_args()
# Extract changed lines for each file.
filename = None
lines_by_file = {}
for line in sys.stdin:
match = re.search(r"^\+\+\+\ (.*?/){%s}(\S*)" % args.p, line)
if match:
filename = match.group(2)
if filename is None:
continue
if args.regex is not None:
if not re.match("^%s$" % args.regex, filename):
continue
else:
if not re.match("^%s$" % args.iregex, filename, re.IGNORECASE):
continue
match = re.search(r"^@@.*\+(\d+)(,(\d+))?", line)
if match:
start_line = int(match.group(1))
line_count = 1
if match.group(3):
line_count = int(match.group(3))
if line_count == 0:
continue
end_line = start_line + line_count - 1
lines_by_file.setdefault(filename, []).extend(
["-lines", str(start_line) + ":" + str(end_line)]
)
# Reformat files containing changes in place.
# We need to count amount of bytes generated in the output of
# clang-format-diff. If clang-format-diff doesn't generate any bytes it
# means there is nothing to format.
format_line_counter = 0
for filename, lines in lines_by_file.items():
if args.i and args.verbose:
print("Formatting {}".format(filename))
command = [args.binary, filename]
if args.i:
command.append("-i")
if args.sort_includes:
command.append("-sort-includes")
command.extend(lines)
if args.style:
command.extend(["-style", args.style])
p = subprocess.Popen(
command,
stdout=subprocess.PIPE,
stderr=None,
stdin=subprocess.PIPE,
universal_newlines=True,
)
stdout, _ = p.communicate()
if p.returncode != 0:
sys.exit(p.returncode)
if not args.i:
with open(filename) as f:
code = f.readlines()
formatted_code = StringIO(stdout).readlines()
diff = difflib.unified_diff(
code,
formatted_code,
filename,
filename,
"(before formatting)",
"(after formatting)",
)
diff_string = "".join(diff)
if diff_string:
format_line_counter += sys.stdout.write(diff_string)
if format_line_counter > 0:
sys.exit(1)
if __name__ == "__main__":
main()

6586
debian/changelog vendored Normal file

File diff suppressed because it is too large Load diff

6
debian/clean vendored Normal file
View file

@ -0,0 +1,6 @@
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

216
debian/clean-up-unmanaged-libraries vendored Executable file
View file

@ -0,0 +1,216 @@
#!/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 Normal file
View file

@ -0,0 +1,208 @@
# 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 Normal file
View file

@ -0,0 +1,204 @@
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 Normal file
View file

@ -0,0 +1,107 @@
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 Normal file
View file

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

18
debian/gbp.conf vendored Normal file
View file

@ -0,0 +1,18 @@
[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

12
debian/gio-launch-desktop vendored Executable file
View file

@ -0,0 +1,12 @@
#!/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 "$@"

2
debian/libglib2.0-0.dirs vendored Normal file
View file

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

7
debian/libglib2.0-0.install vendored Normal file
View file

@ -0,0 +1,7 @@
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

7
debian/libglib2.0-0.lintian-overrides vendored Normal file
View file

@ -0,0 +1,7 @@
# 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/

68
debian/libglib2.0-0.postinst.in vendored Normal file
View file

@ -0,0 +1,68 @@
#!/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:

21
debian/libglib2.0-0.postrm.in vendored Normal file
View file

@ -0,0 +1,21 @@
#! /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

4381
debian/libglib2.0-0.symbols vendored Normal file

File diff suppressed because it is too large Load diff

2
debian/libglib2.0-0.triggers.in vendored Normal file
View file

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

13
debian/libglib2.0-bin.install vendored Normal file
View file

@ -0,0 +1,13 @@
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*

2
debian/libglib2.0-bin.links vendored Normal file
View file

@ -0,0 +1,2 @@
/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

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

1
debian/libglib2.0-data.install vendored Normal file
View file

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

19
debian/libglib2.0-dev-bin.install vendored Normal file
View file

@ -0,0 +1,19 @@
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*

15
debian/libglib2.0-dev.README.Debian vendored Normal file
View file

@ -0,0 +1,15 @@
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

14
debian/libglib2.0-dev.install vendored Normal file
View file

@ -0,0 +1,14 @@
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

14
debian/libglib2.0-doc.doc-base.gio vendored Normal file
View file

@ -0,0 +1,14 @@
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

12
debian/libglib2.0-doc.doc-base.glib vendored Normal file
View file

@ -0,0 +1,12 @@
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

15
debian/libglib2.0-doc.doc-base.gobject vendored Normal file
View file

@ -0,0 +1,15 @@
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

3
debian/libglib2.0-doc.install vendored Normal file
View file

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

3
debian/libglib2.0-doc.links vendored Normal file
View file

@ -0,0 +1,3 @@
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

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

6
debian/libglib2.0-doc.maintscript vendored Normal file
View file

@ -0,0 +1,6 @@
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~

2
debian/libglib2.0-tests.install vendored Normal file
View file

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

View file

@ -0,0 +1,12 @@
# 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]

2
debian/libglib2.0-udeb.install vendored Normal file
View file

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

View file

@ -0,0 +1,2 @@
# 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

@ -0,0 +1,38 @@
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

@ -0,0 +1,167 @@
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

@ -0,0 +1,51 @@
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

@ -0,0 +1,36 @@
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

@ -0,0 +1,33 @@
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

@ -0,0 +1,70 @@
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

@ -0,0 +1,70 @@
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

@ -0,0 +1,25 @@
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

@ -0,0 +1,32 @@
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

@ -0,0 +1,48 @@
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

@ -0,0 +1,37 @@
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

@ -0,0 +1,35 @@
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

@ -0,0 +1,29 @@
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

@ -0,0 +1,30 @@
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

@ -0,0 +1,36 @@
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

@ -0,0 +1,117 @@
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

@ -0,0 +1,28 @@
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

@ -0,0 +1,36 @@
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

@ -0,0 +1,94 @@
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

@ -0,0 +1,201 @@
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

@ -0,0 +1,87 @@
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

@ -0,0 +1,406 @@
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

@ -0,0 +1,104 @@
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

@ -0,0 +1,74 @@
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

@ -0,0 +1,382 @@
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

@ -0,0 +1,378 @@
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

@ -0,0 +1,63 @@
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

@ -0,0 +1,71 @@
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

@ -0,0 +1,26 @@
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

@ -0,0 +1,40 @@
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

@ -0,0 +1,105 @@
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

@ -0,0 +1,125 @@
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

@ -0,0 +1,21 @@
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

@ -0,0 +1,280 @@
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

@ -0,0 +1,89 @@
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

@ -0,0 +1,290 @@
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

@ -0,0 +1,146 @@
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

@ -0,0 +1,40 @@
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

@ -0,0 +1,60 @@
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

@ -0,0 +1,80 @@
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 Normal file
View file

@ -0,0 +1,41 @@
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 Executable file
View file

@ -0,0 +1,296 @@
#!/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

22
debian/set-cross-properties vendored Executable file
View file

@ -0,0 +1,22 @@
#!/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 Normal file
View file

@ -0,0 +1,10 @@
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})

1
debian/source/format vendored Normal file
View file

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

170
debian/tests/bug896019 vendored Executable file
View file

@ -0,0 +1,170 @@
#!/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:

2
debian/tests/bug896019-biarch vendored Executable file
View file

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

Some files were not shown because too many files have changed in this diff Show more