Ethereal-dev: [Ethereal-dev] patch for localtime(3) and gmtime(3) returning NULL
Note: This archive is from the project's previous web site, ethereal.com. This list is no longer active.
From: Scott Renfro <scott@xxxxxxxxxx>
Date: Sat, 14 Jul 2001 23:56:42 -0700
In all but one place where ethereal uses localtime(3) and gmtime(3), the code assumes that a valid pointer was returned. This is not always the case. On some platforms, these functions return NULL as an error indicator, either because they don't know the timezone (in the case of localtime), or the time provided wasn't considered representable. In particular, the Microsoft CRT returns null when the time_t value passed is negative. Although this isn't likely to happen for a few years as a result of reading the clock, when reading arbitrary data from the network, anything is possible. This lead to a null pointer exception decoding such a frame with the latest release on win32 (no problem -- other than a date in the year 1968 -- on FreeBSD. This patch wraps the use of the pointer returned by localtime or gmtime in an if/else that ensures the pointer is not NULL before dereferencing it. If the pointer is null, a default value is stored in the buffer. For column functions, the value is the empty string. For all other functions (these are either in epan or in dissectors, but the resulting string ends up in the display where there's more room than the column), the string "Not representable" is stored. I think I hit all calls to these functions in the source tree (at least cscope says I did ;-) cheers, --Scott -- Scott Renfro <scott@xxxxxxxxxx> +1 650 862 4206
Index: packet-diameter.c =================================================================== RCS file: /cvsroot/ethereal/packet-diameter.c,v retrieving revision 1.23 diff -u -r1.23 packet-diameter.c --- packet-diameter.c 2001/06/18 02:17:45 1.23 +++ packet-diameter.c 2001/07/15 06:32:31 @@ -702,12 +702,16 @@ #endif case DIAMETER_TIME: { - struct tm lt; + struct tm *lt; intval=pntohl(input); intval -= NTP_TIME_DIFF; - lt=*localtime((time_t *)&intval); - strftime(buffer, 1024, - "%a, %d %b %Y %H:%M:%S %z",<); + lt=localtime((time_t *)&intval); + if (lt != NULL) { + strftime(buffer, 1024, + "%a, %d %b %Y %H:%M:%S %z",lt); + } else { + strncpy(buffer, "Not representable", 1024); + } } default: /* Do nothing */ Index: packet-ntp.c =================================================================== RCS file: /cvsroot/ethereal/packet-ntp.c,v retrieving revision 1.28 diff -u -r1.28 packet-ntp.c --- packet-ntp.c 2001/06/18 02:17:50 1.28 +++ packet-ntp.c 2001/07/15 06:32:35 @@ -236,10 +236,14 @@ } else { temptime = tempstmp - (guint32) NTP_BASETIME; bd = gmtime(&temptime); - fractime = bd->tm_sec + tempfrac / 4294967296.0; - snprintf(buff, NTP_TS_SIZE, "%04d-%02d-%02d %02d:%02d:%07.4f UTC", - bd->tm_year + 1900, bd->tm_mon + 1, bd->tm_mday, - bd->tm_hour, bd->tm_min, fractime); + if (bd != NULL) { + fractime = bd->tm_sec + tempfrac / 4294967296.0; + snprintf(buff, NTP_TS_SIZE, "%04d-%02d-%02d %02d:%02d:%07.4f UTC", + bd->tm_year + 1900, bd->tm_mon + 1, bd->tm_mday, + bd->tm_hour, bd->tm_min, fractime); + } else { + strncpy(buff, "Not representable", NTP_TS_SIZE); + } } return buff; } Index: packet-srvloc.c =================================================================== RCS file: /cvsroot/ethereal/packet-srvloc.c,v retrieving revision 1.24 diff -u -r1.24 packet-srvloc.c --- packet-srvloc.c 2001/06/18 02:17:53 1.24 +++ packet-srvloc.c 2001/07/15 06:32:39 @@ -193,12 +193,16 @@ seconds = tvb_get_ntohl(tvb, offset) - 2208988800ul; stamp = gmtime(&seconds); - floatsec = stamp->tm_sec + tvb_get_ntohl(tvb, offset + 4) / 4294967296.0; - proto_tree_add_text(tree, tvb, offset, 8, - "Timestamp: %04d-%02d-%02d %02d:%02d:%07.4f UTC", - stamp->tm_year + 1900, stamp->tm_mon + 1, - stamp->tm_mday, stamp->tm_hour, stamp->tm_min, - floatsec); + if (stamp != NULL) { + floatsec = stamp->tm_sec + tvb_get_ntohl(tvb, offset + 4) / 4294967296.0; + proto_tree_add_text(tree, tvb, offset, 8, + "Timestamp: %04d-%02d-%02d %02d:%02d:%07.4f UTC", + stamp->tm_year + 1900, stamp->tm_mon + 1, + stamp->tm_mday, stamp->tm_hour, stamp->tm_min, + floatsec); + } else { + proto_tree_add_text(tree, tvb, offset, 8, "Timestamp not representable"); + } proto_tree_add_text(tree, tvb, offset + 8, 2, "Block Structure Desciptor: %u", tvb_get_ntohs(tvb, offset + 8)); length = tvb_get_ntohs(tvb, offset + 10); Index: epan/column-utils.c =================================================================== RCS file: /cvsroot/ethereal/epan/column-utils.c,v retrieving revision 1.3 diff -u -r1.3 epan/column-utils.c --- epan/column-utils.c 2001/04/02 10:38:26 1.3 +++ epan/column-utils.c 2001/07/15 06:32:42 @@ -248,15 +248,19 @@ then = fd->abs_secs; tmp = localtime(&then); - snprintf(fd->cinfo->col_buf[col], COL_MAX_LEN, - "%04d-%02d-%02d %02d:%02d:%02d.%04ld", - tmp->tm_year + 1900, - tmp->tm_mon + 1, - tmp->tm_mday, - tmp->tm_hour, - tmp->tm_min, - tmp->tm_sec, - (long)fd->abs_usecs/100); + if (tmp != NULL) { + snprintf(fd->cinfo->col_buf[col], COL_MAX_LEN, + "%04d-%02d-%02d %02d:%02d:%02d.%04ld", + tmp->tm_year + 1900, + tmp->tm_mon + 1, + tmp->tm_mday, + tmp->tm_hour, + tmp->tm_min, + tmp->tm_sec, + (long)fd->abs_usecs/100); + } else { + fd->cinfo->col_buf[col][0] = '\0'; + } fd->cinfo->col_data[col] = fd->cinfo->col_buf[col]; } @@ -286,11 +290,15 @@ then = fd->abs_secs; tmp = localtime(&then); - snprintf(fd->cinfo->col_buf[col], COL_MAX_LEN, "%02d:%02d:%02d.%04ld", - tmp->tm_hour, - tmp->tm_min, - tmp->tm_sec, - (long)fd->abs_usecs/100); + if (tmp != NULL) { + snprintf(fd->cinfo->col_buf[col], COL_MAX_LEN, "%02d:%02d:%02d.%04ld", + tmp->tm_hour, + tmp->tm_min, + tmp->tm_sec, + (long)fd->abs_usecs/100); + } else { + fd->cinfo->col_buf[col][0] = '\0'; + } fd->cinfo->col_data[col] = fd->cinfo->col_buf[col]; } Index: epan/to_str.c =================================================================== RCS file: /cvsroot/ethereal/epan/to_str.c,v retrieving revision 1.9 diff -u -r1.9 epan/to_str.c --- epan/to_str.c 2001/07/13 00:27:51 1.9 +++ epan/to_str.c 2001/07/15 06:32:45 @@ -411,15 +411,18 @@ } tmp = localtime(&abs_time->tv_sec); - sprintf(cur, "%s %2d, %d %02d:%02d:%02d.%06ld", - mon_names[tmp->tm_mon], - tmp->tm_mday, - tmp->tm_year + 1900, - tmp->tm_hour, - tmp->tm_min, - tmp->tm_sec, - (long)abs_time->tv_usec); - + if (tmp) { + sprintf(cur, "%s %2d, %d %02d:%02d:%02d.%06ld", + mon_names[tmp->tm_mon], + tmp->tm_mday, + tmp->tm_year + 1900, + tmp->tm_hour, + tmp->tm_min, + tmp->tm_sec, + (long)abs_time->tv_usec); + } else { + strncpy(cur, "Not representable", sizeof(str[0])); + } return cur; } Index: wiretap/netmon.c =================================================================== RCS file: /cvsroot/ethereal/wiretap/netmon.c,v retrieving revision 1.38 diff -u -r1.38 wiretap/netmon.c --- wiretap/netmon.c 2001/07/13 00:55:58 1.38 +++ wiretap/netmon.c 2001/07/15 06:32:50 @@ -635,14 +635,24 @@ file_hdr.network = htoles(wtap_encap[wdh->encap]); tm = localtime(&netmon->first_record_time.tv_sec); - file_hdr.ts_year = htoles(1900 + tm->tm_year); - file_hdr.ts_month = htoles(tm->tm_mon + 1); - file_hdr.ts_dow = htoles(tm->tm_wday); - file_hdr.ts_day = htoles(tm->tm_mday); - file_hdr.ts_hour = htoles(tm->tm_hour); - file_hdr.ts_min = htoles(tm->tm_min); - file_hdr.ts_sec = htoles(tm->tm_sec); - file_hdr.ts_msec = htoles(netmon->first_record_time.tv_usec/1000); + if (tm != NULL) { + file_hdr.ts_year = htoles(1900 + tm->tm_year); + file_hdr.ts_month = htoles(tm->tm_mon + 1); + file_hdr.ts_dow = htoles(tm->tm_wday); + file_hdr.ts_day = htoles(tm->tm_mday); + file_hdr.ts_hour = htoles(tm->tm_hour); + file_hdr.ts_min = htoles(tm->tm_min); + file_hdr.ts_sec = htoles(tm->tm_sec); + } else { + file_hdr.ts_year = htoles(1900 + 0); + file_hdr.ts_month = htoles(0 + 1); + file_hdr.ts_dow = htoles(0); + file_hdr.ts_day = htoles(0); + file_hdr.ts_hour = htoles(0); + file_hdr.ts_min = htoles(0); + file_hdr.ts_sec = htoles(0); + } + file_hdr.ts_msec = htoles(netmon->first_record_time.tv_usec/1000); /* XXX - what about rounding? */ file_hdr.frametableoffset = htolel(netmon->frame_table_offset); file_hdr.frametablelength = Index: wiretap/ngsniffer.c =================================================================== RCS file: /cvsroot/ethereal/wiretap/ngsniffer.c,v retrieving revision 1.64 diff -u -r1.64 wiretap/ngsniffer.c --- wiretap/ngsniffer.c 2001/07/06 00:17:36 1.64 +++ wiretap/ngsniffer.c 2001/07/15 06:33:01 @@ -1204,11 +1204,16 @@ if (priv->first_frame) { priv->first_frame=FALSE; tm = localtime(&phdr->ts.tv_sec); - start_date = (tm->tm_year - (1980 - 1900)) << 9; - start_date |= (tm->tm_mon + 1) << 5; - start_date |= tm->tm_mday; - /* record the start date, not the start time */ - priv->start = phdr->ts.tv_sec - (3600*tm->tm_hour + 60*tm->tm_min + tm->tm_sec); + if (tm != NULL) { + start_date = (tm->tm_year - (1980 - 1900)) << 9; + start_date |= (tm->tm_mon + 1) << 5; + start_date |= tm->tm_mday; + /* record the start date, not the start time */ + priv->start = phdr->ts.tv_sec - (3600*tm->tm_hour + 60*tm->tm_min + tm->tm_sec); + } else { + start_date = 0; + priv->start = 0; + } /* "sniffer" version ? */ maj_vers = 4;
- Follow-Ups:
- Prev by Date: [Ethereal-dev] Re: [tcpdump-workers] New capture file format ideas?
- Next by Date: [Ethereal-dev] patch for one character ssl typo
- Previous by thread: [Ethereal-dev] Re: [tcpdump-workers] New capture file format ideas?
- Next by thread: Re: [Ethereal-dev] patch for localtime(3) and gmtime(3) returning NULL
- Index(es):