cedric pushed a commit to branch master. http://git.enlightenment.org/core/elementary.git/commit/?id=c319ea7f77e786a6a8d3208a8c764fb143367322
commit c319ea7f77e786a6a8d3208a8c764fb143367322 Author: Cedric BAIL <[email protected]> Date: Tue Jul 28 20:10:02 2015 +0200 calendar: fix use of strftime. strftime is quite a bad POSIX API. You won't know the size it needs to put the strings in until you did give it enough byte and it could also fail without a clear way to detect it. So this patch work around that and introduce a currently internal helper that will be moved later to Eina. This patch has been triggered by the issue reported and the attempt fix from D2877. --- src/lib/elm_calendar.c | 68 ++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 52 insertions(+), 16 deletions(-) diff --git a/src/lib/elm_calendar.c b/src/lib/elm_calendar.c index 7fd2491..80c1906 100644 --- a/src/lib/elm_calendar.c +++ b/src/lib/elm_calendar.c @@ -27,6 +27,50 @@ static const Evas_Smart_Cb_Description _smart_callbacks[] = { {NULL, NULL} }; +/* This two functions should be moved in Eina for next release. */ +static Eina_Tmpstr * +_eina_tmpstr_strftime(const char *format, const struct tm *tm) +{ + const size_t flen = strlen(format); + size_t buflen = 16; // An arbitrary starting size + char *buf = NULL; + + do { + char *tmp; + size_t len; + + tmp = realloc(buf, buflen * sizeof(char)); + if (!tmp) goto on_error; + buf = tmp; + + len = strftime(buf, buflen, format, tm); + // Check if we have the expected result and return it. + if ((len > 0 && len < buflen) || (len == 0 && flen == 0)) + { + Eina_Tmpstr *r; + + r = eina_tmpstr_add_length(buf, len + 1); + free(buf); + return r; + } + + /* Possibly buf overflowed - try again with a bigger buffer */ + buflen <<= 1; // multiply buffer size by 2 + } while (buflen < 128 * flen); + + on_error: + free(buf); + return NULL; +} + +static char * +_eina_tmpstr_steal(Eina_Tmpstr *s) +{ + char *r = s ? strdup(s) : NULL; + eina_tmpstr_del(s); + return r; +} + static Eina_Bool _key_action_move(Evas_Object *obj, const char *params); static const Elm_Action key_actions[] = { @@ -172,28 +216,19 @@ _disable(Elm_Calendar_Data *sd, static char * _format_month_year(struct tm *selected_time) { - char buf[32]; - - if (!strftime(buf, sizeof(buf), E_("%B %Y"), selected_time)) return NULL; - return strdup(buf); + return _eina_tmpstr_steal(_eina_tmpstr_strftime(E_("%B %Y"), selected_time)); } static char * _format_month(struct tm *selected_time) { - char buf[32]; - - if (!strftime(buf, sizeof(buf), E_("%B"), selected_time)) return NULL; - return strdup(buf); + return _eina_tmpstr_steal(_eina_tmpstr_strftime(E_("%B"), selected_time)); } static char * _format_year(struct tm *selected_time) { - char buf[32]; - - if (!strftime(buf, sizeof(buf), E_("%Y"), selected_time)) return NULL; - return strdup(buf); + return _eina_tmpstr_steal(_eina_tmpstr_strftime(E_("%Y"), selected_time)); } static inline void @@ -1036,18 +1071,19 @@ _elm_calendar_evas_object_smart_add(Eo *obj, Elm_Calendar_Data *priv) for (i = 0; i < ELM_DAY_LAST; i++) { - /* FIXME: I'm not aware of a known max, so if it fails, - * just make it larger. :| */ - char buf[20]; struct tm *info; /* I don't know of a better way of doing it */ info = gmtime(&weekday); if (info) { - if (strftime(buf, sizeof(buf), "%a", info)) + Eina_Tmpstr *buf; + + buf = _eina_tmpstr_strftime("%a", info); + if (buf) { priv->weekdays[i] = eina_stringshare_add(buf); + eina_tmpstr_del(buf); } else { --
