So 11 cases involve direct-to-strtoull(), which means crashing if NULL, 24 cases have some variation of query ? strtoull() : 0 and these two are the questionable cases. The first one looks like a problem, the second one isn't a problem if the flags[] array's values are either 0 or 1.
I'll write up the db_get_result_u64() function sometime today along with the changes to db.c and post it to SourceForge and/or the mailing list. This is the only chunk that I found that handles NULL separately from 0: result_string = db_get_result(0, 0); if (result_string) *message_size = strtoull(result_string, NULL, 10); else { trace(TRACE_ERROR, "%s,%s: no result set after requesting msgsize " "of msg [%llu]\n", __FILE__, __FUNCTION__, message_idnr); db_free_result(); return -1; } db_free_result(); return 1; This one looks like it treats NULL separately, but I'd bet that 0 is the other possible value for the flags field: if (db_num_rows() > 0) { for (i = 0; i < IMAP_NFLAGS; i++) { query_result = db_get_result(0, i); if (query_result && query_result[0] != '0') flags[i] = 1; } } Here's a funny one, btw, which looks like a bizarre glorified strdup() to me: if (!(tmp_name = my_malloc((tmp_name_len + 1) * sizeof(char)))) { trace(TRACE_ERROR,"%s,%s: error allocating memory", __FILE__, __FUNCTION__); return -1; } strncpy(tmp_name, query_result, tmp_name_len); tmp_name[tmp_name_len] = '\0'; Aaron Ilja Booij <[EMAIL PROTECTED]> said: > Hi > > Aaron Stone wrote: > > > Since directly testing the return value is easy enough, we should do that > > rather than test other things that *should* mean that the return value is > > non-NULL. Based on some grepping, literally 55% of calls to db_get_result() > > are passed to strtoull() within the next two lines of code. 11 calls are on > > the same line of code (presumably waiting to die when db_get_result() > > returns > > a NULL for whatever reasons it might -- no data, db error, etc.) > You're right. Otherwise a new error is introduced way to easily. :) > > > > [dbmail-2.0rc2]$ grep db_get_result db.c | wc > > 67 298 2930 > > [dbmail-2.0rc2]$ grep db_get_result db.c | grep strtoull | wc > > 11 64 645 > > [dbmail-2.0rc2]$ grep db_get_result -A1 db.c | grep strtoull | wc > > 19 132 1194 > > [dbmail-2.0rc2]$ grep db_get_result -A2 db.c | grep strtoull | wc > > 37 234 2143 > > [dbmail-2.0rc2]$ grep db_get_result -A10 db.c | grep strtoull | wc > > 37 234 2143 > > > > > > Since it's only 37 cases, I'll go through and look to see if any of them > > have > > special handling for the NULL case, or if they just use 0. If it turns out > > that way, then I'll write up a db_get_result_u64() function. > Great, sounds like a plan. :D > > Ilja > > > Ilja Booij <[EMAIL PROTECTED]> said: > > > > > >>Hi, > >> > >>I wouldn't now actually.. I guess there are functions for which strtoull > >>can return a 0. > >> > >>auth_getmaxmailsize() is an example of this. When the maxmail_size for a > >>user is 0, strtoull will return 0. > >> > >>I agree with the fact that we need to clean up the code in db.c to deal > >>with db_get_result() returning NULL. > >> > >>Maybe we should pay more attention to the reason why db_get_result() > >>returns 0. > >> > >>In dbpgsql.c/dbmysql.c, db_get_result() will return 0 if the result set > >>is NULL, of if the row, field combination asked is not in the result > >>set. Before every db_get_result() we could make sure we are only asking > >>for a valid row, by making sure the row_nr we are asking for is < > >>db_num_rows(). > >>db_num_rows() will return 0 if there are no rows in the reslt set. If > >>this is the case, no call to db_get_result() should be done. > >> > >>Still, I guess we should make sure that no call will be made to > >>strtoull() when the query_result is NULL. > >> > >>Ilja > >> > >>Aaron Stone wrote: > >> > >> > >>>It occurs to me that the correct solution really is to have a function that > >>>integrates a properly validated strtoull() call, but what I can't figure > >>>out > >>>is how to determine the difference between a 0 and a NULL result -- that > >>>is, > >>>if we get a NULL within the function, and return 0, it's no different than > >>>actually getting 0. Are there potential consumer functions that need to > >>>differentiate these situations? > >>> > >>>Aaron > >>> > >>> > >>>"Aaron Stone" <[EMAIL PROTECTED]> said: > >>> > >>> > >>> > >>>>I just got a crash while trying to make a delivery to a non-existant > >>>>user. I > >>>>skipped past the part that made sure that the user exists and so was able > >>>>to > >>>>discover a pretty significant bad idiom that's widely used in db.c > >>>> > >>>>The problem is that db_get_result() can return NULL if there's actually no > >>>>results to find. In a number of cases, the count of returned rows in not > >>>>checked, db_get_result() is called, and it is not tested for a valid > >>>>return > >>>>before being derefenced or passed as an argument to a standard library > >>>>function, such as strtoull(), that apparently cannot handle a NULL first > >>> > >>>argument. > >>> > >>> > >>>>In a few places there is a better idiom (this is from db_createsession(): > >>>> > >>>> tmpmessage.msize = > >>>> query_result ? strtoull(query_result, NULL, 10) : 0; > >>>> > >>>>db.c should really be audited and this better idiom put wherever possible. > >>>>Note that it is entirely possible to have a situation in which even after > >>>>checking everything that indicates that a value should be returned, > >>>>db_get_result() can still return a NULL value; it's output should always > >>>>be > >>>>checked! > >>>> > >>>>Alternatively, since at least half of the calls to db_get_result() are fed > >>>>into strtoull() right away, why not have a function that does the proper > >>>>result validation and then makes the call to strtoull() and returns a > >>>>u64_t? > >>>> > >>>>Aaron > >>>>_______________________________________________ > >>>>Dbmail-dev mailing list > >>>>Dbmail-dev@dbmail.org > >>>>http://twister.fastxs.net/mailman/listinfo/dbmail-dev > >>>> > >>> > >>> > >>> > >>> > >>_______________________________________________ > >>Dbmail-dev mailing list > >>Dbmail-dev@dbmail.org > >>http://twister.fastxs.net/mailman/listinfo/dbmail-dev > >> > > > > > > > > > _______________________________________________ > Dbmail-dev mailing list > Dbmail-dev@dbmail.org > http://twister.fastxs.net/mailman/listinfo/dbmail-dev > --