GNOME Bugzilla – Bug 357807
gtk_calendar_select_month breaks when using a big year number
Last modified: 2018-02-10 03:38:28 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.
+ Trace 73308
Thread NaN (LWP 25318)
I guess the right solution would be to clamp the year property to a lower value than G_MAXINT.
Created attachment 73538 [details] [review] Proposed patch Fixes the problem clamping the year property to the range (0, MAXUSHORT)
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.
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.
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.
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.