After an evaluation, GNOME has moved from Bugzilla to GitLab. Learn more about GitLab.
No new issues can be reported in GNOME Bugzilla anymore.
To report an issue in a GNOME project, go to GNOME GitLab.
Do not go to GNOME Gitlab for: Bluefish, Doxygen, GnuCash, GStreamer, java-gnome, LDTP, NetworkManager, Tomboy.
Bug 357807 - gtk_calendar_select_month breaks when using a big year number
gtk_calendar_select_month breaks when using a big year number
Status: RESOLVED OBSOLETE
Product: gtk+
Classification: Platform
Component: Widget: GtkCalendar
unspecified
Other All
: Normal normal
: ---
Assigned To: gtk-bugs
gtk-bugs
Depends on:
Blocks:
 
 
Reported: 2006-09-26 12:52 UTC by Iago Toral
Modified: 2018-02-10 03:38 UTC
See Also:
GNOME target: ---
GNOME version: 2.17/2.18


Attachments
Proposed patch (955 bytes, patch)
2006-09-28 07:37 UTC, Iago Toral
reviewed Details | Review

Description Iago Toral 2006-09-26 12:52:07 UTC
Please describe the problem:
The "year" property of GtkCalendar specifies a maximum value of G_MAXINT. However, setting G_MAXINT as value for the year in "gtk_calendar_select_month" produces random results and, under certain circunstances, Segmentation Fault at calendar destruction time.

Steps to reproduce:
#include <gtk/gtk.h>

int main ()
{
  GtkCalendar *calendar;
  guint month = 10;
  guint year = G_MAXINT;

  gtk_init (0, NULL);

  calendar = GTK_CALENDAR (gtk_calendar_new ());

  gtk_calendar_select_month (calendar, month, year);
  gtk_calendar_get_date (calendar, &year, &month, NULL);

  g_print ("\nYear=%d, month=%d\n", year, month);

  gtk_widget_destroy (GTK_WIDGET (calendar));
  return 0;
}


Actual results:
Year=1, month=1
Segmentation Fault

If I set month=11 instead of month=10 I get:
Year=1, month=1
and the program finished nicely.

Expected results:
Year=<value of G_MAXINT>, month=11
The program finishes nicely.

Does this happen every time?
Yes

Other information:
The problem seems to be in the static function "year_to_days":
static glong 
year_to_days(guint year)
{
  return( year * 365L + (year / 4) - (year / 100) + (year / 400) );
}

which it is trying to multiply a year (up to G_MAXINT) by 365. This results in a number that's much bigger than the range of a glong, at least for 32-bit architectures. Here is what happens using gdb:

146       return( year_to_days(--year) + days_in_months[lp][mm] + dd );
(gdb) s
year_to_days (year=2147483646) at gtkcalendar.c:134
134       return( year * 365L + (year / 4) - (year / 100) + (year / 400) );
(gdb) print year
$1 = 2147483646
(gdb) print year * 365L
$2 = 2147482918

Which is obviously wrong.

This result is used in further calculations which leads to a random behavior. When it produces a Segmentation Fault the stack trace is:

Program received signal SIGSEGV, Segmentation fault.

Thread NaN (LWP 25318)

  • #0 IA__g_type_check_instance_cast
    at gtype.c line 3141
  • #1 gtk_widget_dispose
    at gtkwidget.c line 6875
  • #2 IA__g_object_run_dispose
    at gobject.c line 570
  • #3 IA__gtk_object_destroy
    at gtkobject.c line 403
  • #4 IA__gtk_widget_destroy
    at gtkwidget.c line 2168
  • #5 fx_teardown_default_gtk_calendar
    at check-gtkcalendar.c line 36
  • #6 tcase_run_checked_teardown
  • #7 tcase_run_tfun_nofork
  • #8 srunner_iterate_tcase_tfuns
  • #9 srunner_run_tcase
  • #10 srunner_iterate_suites
  • #11 srunner_run_all
  • #12 main
    at check-main.c line 16

I guess the right solution would be to clamp the year property to a lower value than G_MAXINT.
Comment 1 Iago Toral 2006-09-28 07:37:03 UTC
Created attachment 73538 [details] [review]
Proposed patch

Fixes the problem clamping the year property to the range (0, MAXUSHORT)
Comment 2 Matthias Clasen 2006-10-02 02:00:51 UTC
I don't think it makes much sense to restrict the year range in this way, unless we can figure out where the calendaric calculations stop making sense, exactly. 
The dates stop being meaningful if you go earlier than 1700-something, but we do not restrict the year range for that either.
Comment 3 Iago Toral 2006-10-02 07:08:21 UTC
Sincerely, I don't see much difference between restricting the year to G_MAXUSHORT and restricting it to G_MAXINT. Anyway, if you think that the value range should not be restricted that way, I see two other ways to fix the problem (though I think they are worse approaches):

1. Try using wider data types to store and operate values that are above the long range (long long, double, etc).

2. Rethink the algorithms used in order to avoid numbers that are above the long range.
Comment 4 Björn Lindqvist 2008-06-26 23:18:20 UTC
I think it would be better to use g_return_val_if_fail (year <= X); where X is some random integer < G_MAXSHORT instead. If the year value is to large (or to small) you probably want a warning instead of getting it silently clamped. 
Comment 5 Matthias Clasen 2018-02-10 03:38:28 UTC
We're moving to gitlab! As part of this move, we are closing bugs that haven't seen activity in more than 5 years. If this issue is still imporant to you and
still relevant with GTK+ 3.22 or master, please consider creating a gitlab issue
for it.