Padding numbers with a typical space character doesn't align them well
because it has a different size. Instead, we need to use the "U+2007"
figure (numeric) space that has the same size as a numerical digit.
This is only visible when using the `tnum` font feature that
makes numbers monospace.
Closes#2655
These have all been added manually, as I’ve finished all the files which
I can automatically detect.
All the license headers in this commit are for LGPL-2.1-or-later, and
all have been double-checked against the license paragraph in the file
header.
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
Helps: #1415
This introduces no functional changes, but reworks the array indexing so
that scan-build has a better idea about the array bounds. This squashes
the scan-build warning:
```
../../../../source/glib/glib/gdatetime.c:2292:20: warning: The left operand of '>=' is a garbage value [core.UndefinedBinaryOperatorResult]
if (days [i] >= day_of_year)
~~~~~~~~ ^
```
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
Helps: #1767
The current use of %Y does not take into account that %Y will
not pad the year with 0's, meanwhile ISO8601 does expect a full
YYYY format for all dates. This breaks the formatting with dates
prior to the year 1000.
Split this into %C%y so 2-digit, 0-padded century and year are
printed separately, this gives the expected YYYY format.
Functions (_g_get_time_charset and _g_get_ctype_charset) to get LC_TIME and LC_CTYPE charset
by using nl_langinfo with _NL_TIME_CODESET and CODESET).
Another functions (_g_locale_time_to_utf8 and _g_locale_ctype_to_utf8) which uses thel and format
the input string accordingly.
Add new test cases with mixing UTF8 and non UTF8 LC_TIME along with UTF8
and non UTF8 LC_MESSAGES.
Closed#2055
Signed-off-by: Frederic Martinsons <frederic.martinsons@sigfox.com>
Both are provided by libm, but `isnan()` is provided as a macro, whereas
`isfinite()` is an actual function, and hence libm has to be available
at runtime. That didn’t trivially work on FreeBSD, resulting in this
refactor.
`isfinite(x)` is equivalent to `!isnan(x) && !isinfinite(x)`. The case
of `x` being (negative or positive) infinity is already handled by the
range checks on the next line, so it’s safe to switch to `isnan()` here.
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
Rather than parsing the seconds in an ISO 8601 date/time using a pair of
floating point numbers (numerator and denominator), use two integers
instead. This avoids issues around floating point precision, and also
makes it easier to check for potential overflow from overlong inputs.
This last point means that the `isfinite()` check can be removed, as it
was covering the case where a NAN was generated, which isn’t now
possible using integer arithmetic.
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
The fiendish thing about NAN is that it never compares TRUE against
anything, so the limit checks `seconds < 0.0 || seconds >= 60.0` were
never triggering.
oss-fuzz#28473
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
These variables were already (correctly) accessed atomically. The
`volatile` qualifier doesn’t help with that.
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
Helps: #600
Otherwise it could possibly overflow on 32-bit machines if `year` is
high enough, although I don’t think that’s possible because of limits
applied on it by callers. This should shut Coverity up though.
The limits applied by callers could be circumvented by calling (say)
`g_date_time_add_years()` multiple times. That’s a bug, but not one I’m
going to fix today.
Coverity CID: #1159479
Signed-off-by: Philip Withnall <withnall@endlessm.com>
Many locales have no concept of AM/PM notation, and it’s confusing to
them. It’s an Anglo-centric concept which doesn’t belong in the API at
this level — instead, programs should use more generic format specifiers
which leave the details of how to format a date/time to the locale.
Signed-off-by: Philip Withnall <withnall@endlessm.com>
Fixes: #2082
It was possible to pass in (for example) an invalid year to
g_date_time_new_week(), which would be passed on to g_date_time_new(),
which would (correctly) return `NULL` — but then
g_date_time_get_week_number() would try to dereference that.
Includes a test case.
oss-fuzz#17648
Signed-off-by: Philip Withnall <withnall@endlessm.com>
It was possible to pass in (for example) an invalid hour to
g_date_time_new_ordinal(), which would be passed on to
g_date_time_new(), which would (correctly) return `NULL` — but then
g_date_time_new_ordinal() would try to dereference that.
Includes some test cases.
oss-fuzz#16103
oss-fuzz#17183
Signed-off-by: Philip Withnall <withnall@endlessm.com>
Some malformed ISO 8601 date/time strings were causing an assertion
failure when passed to `g_date_time_new_from_iso8601()`, due to a
mismatch between the bounds checking of timezone offsets in `GDateTime`
and `GTimeZone`. Fix that and add a unit test for it.
oss-fuzz#16101
Signed-off-by: Philip Withnall <withnall@endlessm.com>
This requires some reworking of the internal g_date_time_new_from_unix()
function, since it previously operated in seconds, which wasn’t high
enough resolution — the g_get_current_time() code path used to operate
in microseconds.
Signed-off-by: Philip Withnall <withnall@endlessm.com>
Helps: #1438
This is a simple wrapper around g_date_time_format_iso8601() which
always produces ISO 8601 dates, without people having to remember the
format string for them (and with the convenience of terminating UTC
dates with ‘Z’ rather than ‘+00’).
Signed-off-by: Philip Withnall <withnall@endlessm.com>
Helps: #1438
glib/gdatetime.c: In function ‘get_iso8601_int’:
glib/gdatetime.c:1142:17: error: comparison of integer expressions of different signedness: ‘gint’ {aka ‘int’} and ‘gsize’ {aka ‘long unsigned int’} [-Werror=sign-compare]
for (i = 0; i < length; i++)
^
glib/gdatetime.c: In function ‘get_iso8601_seconds’:
glib/gdatetime.c:1175:9: error: comparison of integer expressions of different signedness: ‘gint’ {aka ‘int’} and ‘gsize’ {aka ‘long unsigned int’} [-Werror=sign-compare]
if (i == length)
^~
glib/gdatetime.c:1178:12: error: comparison of integer expressions of different signedness: ‘gint’ {aka ‘int’} and ‘gsize’ {aka ‘long unsigned int’} [-Werror=sign-compare]
for (; i < length; i++)
^
In file included from glib/glibconfig.h:9,
from glib/gtypes.h:32,
from glib/gtimezone.h:27,
from glib/gdatetime.h:31,
from glib/gdatetime.c:62:
glib/gdatetime.c: In function ‘initialize_alt_digits’:
glib/gdatetime.c:2806:27: error: comparison of integer expressions of different signedness: ‘gsize’ {aka ‘long unsigned int’} and ‘long int’ [-Werror=sign-compare]
g_assert (digit_len < buffer + sizeof (buffer) - buffer_end);
^
glib/gmacros.h:455:25: note: in definition of macro ‘G_LIKELY’
#define G_LIKELY(expr) (expr)
^~~~
glib/gdatetime.c:2806:7: note: in expansion of macro ‘g_assert’
g_assert (digit_len < buffer + sizeof (buffer) - buffer_end);
^~~~~~~~
In date time formatting routine, instead of converting from UTF-8 to
locale charset and then from locale charset to UTF-8, store all
intermediate result in UTF-8.
This solves the issue where user provided UTF-8 format string might be
unrepresentable in the current locale charset.
Fixes issue #1605.
Formatting code for `%z` specifier incorrectly assumed that sign of
offset from UTC can be recovered from the number of hours alone, which
is not true for offsets between -01:00 and +00:00.
Extract and format sign separately to avoid the problem.
Issue #1337.
Spotted when temporarily compiling with -Wwrite-strings. This only goes
a small way towards making the code base -Wwrite-strings–clean. It
introduces no functional changes, and fixes no bugs.
Signed-off-by: Philip Withnall <withnall@endlessm.com>
Reviewed-by: nobody