[Asterisk-code-review] time: add support for time64 libcs (asterisk[19])

Philip Prindeville asteriskteam at digium.com
Mon Mar 7 15:33:56 CST 2022


Philip Prindeville has uploaded this change for review. ( https://gerrit.asterisk.org/c/asterisk/+/18205 )


Change subject: time: add support for time64 libcs
......................................................................

time: add support for time64 libcs

libcs are implementing changes to fix the year 2038 issue on 32 bit
platforms (see [1]). musl libc already went ahead and implemented it,
starting with musl-1.2.0 (see [2]).

Running asterisk on a 32 bit box with a time64 libc causes some
problems. For instance registering to pjsip doesn't work. The
registration completes fine, but the AOR disappears immediately, making
the registered clients unreachable.

Currently time_t is always expected to be (long). This commit changes
this and instead always uses "lld" when dealing with time_t and casting
the values to be formatted to (long long). The aim is to be future proof
and portable. This was suggested on the musl mailing list ([3]).

When it comes to scanning, no assumptions can be made regarding the type
of the time_t destination. It is unknown as it is depending on the
platform. So we "read into a known-size integer (either int or long
long) and then assign the value to a time_t as a second step" (quote
from [4]).

These changes get rid of the new warnings that appeared with musl-1.2.0 and
make the pjsip registration work again. Below an example warning:

In file included from ../include/asterisk.h:23,
                 from res_pjsip/location.c:19:
res_pjsip/location.c: In function 'expiration_struct2str':
../include/asterisk/astmm.h:270:72: warning: format '%ld' expects argument of type 'long int', but argument 6 has type 'time_t' {aka 'long long int'} [-Wformat=]
  270 |         __ast_asprintf(__FILE__, __LINE__, __PRETTY_FUNCTION__, (ret), (fmt), __VA_ARGS__)
      |                                                                        ^~~~~
res_pjsip/location.c:492:17: note: in expansion of macro 'ast_asprintf'
  492 |         return (ast_asprintf(buf, "%ld", contact->expiration_time.tv_sec) < 0) ? -1 : 0;
      |                 ^~~~~~~~~~~~

[1] https://sourceware.org/glibc/wiki/Y2038ProofnessDesign
[2] https://musl.libc.org/time64.html
[3] https://www.openwall.com/lists/musl/2021/10/27/3
[4] https://stackoverflow.com/questions/4171478/how-to-read-data-into-a-time-t-variable-using-scanf

ASTERISK-29674 #close

Signed-off-by: Sebastian Kemper <sebastian_ml at gmx.net>
Change-Id: Ic8d61b26033f5c486b917e738c9608b0923a844e
---
M include/asterisk/time.h
M res/res_calendar_caldav.c
M res/res_calendar_icalendar.c
M res/res_http_media_cache.c
M res/res_odbc.c
M res/res_pjsip/location.c
M res/res_pjsip/pjsip_options.c
M res/res_pjsip_history.c
M res/res_pjsip_pubsub.c
M res/res_pjsip_registrar.c
M res/res_stir_shaken.c
11 files changed, 34 insertions(+), 19 deletions(-)



  git pull ssh://gerrit.asterisk.org:29418/asterisk refs/changes/05/18205/1

diff --git a/include/asterisk/time.h b/include/asterisk/time.h
index e2ab513..58b5016 100644
--- a/include/asterisk/time.h
+++ b/include/asterisk/time.h
@@ -29,6 +29,9 @@
 #include <sys/time.h>
 #endif
 
+#define TIME_T_FMT "lld"
+#define TIME_T_CAST(x) ((long long)(x))
+
 #ifdef HAVE_UNISTD_H
 #include <unistd.h>
 #endif
diff --git a/res/res_calendar_caldav.c b/res/res_calendar_caldav.c
index 9bdde0e..e109641 100644
--- a/res/res_calendar_caldav.c
+++ b/res/res_calendar_caldav.c
@@ -405,7 +405,7 @@
 			ast_string_field_set(event, uid, event->summary);
 		} else {
 			char tmp[100];
-			snprintf(tmp, sizeof(tmp), "%ld", event->start);
+			snprintf(tmp, sizeof(tmp), "%" TIME_T_FMT, TIME_T_CAST(event->start));
 			ast_string_field_set(event, uid, tmp);
 		}
 	}
diff --git a/res/res_calendar_icalendar.c b/res/res_calendar_icalendar.c
index 999cf0e..756387d 100644
--- a/res/res_calendar_icalendar.c
+++ b/res/res_calendar_icalendar.c
@@ -246,7 +246,7 @@
 			ast_string_field_set(event, uid, event->summary);
 		} else {
 			char tmp[100];
-			snprintf(tmp, sizeof(tmp), "%ld", event->start);
+			snprintf(tmp, sizeof(tmp), "%" TIME_T_FMT, TIME_T_CAST(event->start));
 			ast_string_field_set(event, uid, tmp);
 		}
 	}
diff --git a/res/res_http_media_cache.c b/res/res_http_media_cache.c
index 2bace1e..ae3efcd 100644
--- a/res/res_http_media_cache.c
+++ b/res/res_http_media_cache.c
@@ -150,7 +150,7 @@
 	}
 
 	/* Use 'now' if we didn't get an expiration time */
-	snprintf(time_buf, sizeof(time_buf), "%30lu", actual_expires.tv_sec);
+	snprintf(time_buf, sizeof(time_buf), "%30" TIME_T_FMT, TIME_T_CAST(actual_expires.tv_sec));
 
 	ast_bucket_file_metadata_set(bucket_file, "__actual_expires", time_buf);
 }
@@ -299,15 +299,18 @@
 		ao2_cleanup);
 	struct timeval current_time = ast_tvnow();
 	struct timeval expires = { .tv_sec = 0, .tv_usec = 0 };
+	long long llv;
 
 	if (!metadata) {
 		return 1;
 	}
 
-	if (sscanf(metadata->value, "%lu", &expires.tv_sec) != 1) {
+	if (sscanf(metadata->value, "%" TIME_T_FMT, &llv) != 1) {
 		return 1;
 	}
 
+	expires.tv_sec = llv;
+
 	return ast_tvcmp(current_time, expires) == -1 ? 0 : 1;
 }
 
diff --git a/res/res_odbc.c b/res/res_odbc.c
index 63fdf37..6353556 100644
--- a/res/res_odbc.c
+++ b/res/res_odbc.c
@@ -1029,7 +1029,7 @@
 	/* Dont connect while server is marked as unreachable via negative_connection_cache */
 	negative_cache_expiration = obj->parent->last_negative_connect.tv_sec + obj->parent->negative_connection_cache.tv_sec;
 	if (time(NULL) < negative_cache_expiration) {
-		ast_log(LOG_WARNING, "Not connecting to %s. Negative connection cache for %ld seconds\n", obj->parent->name, negative_cache_expiration - time(NULL));
+		ast_log(LOG_WARNING, "Not connecting to %s. Negative connection cache for %" TIME_T_FMT " seconds\n", obj->parent->name, TIME_T_CAST(negative_cache_expiration - time(NULL)));
 		return ODBC_FAIL;
 	}
 
diff --git a/res/res_pjsip/location.c b/res/res_pjsip/location.c
index bae8a2d..f381165 100644
--- a/res/res_pjsip/location.c
+++ b/res/res_pjsip/location.c
@@ -489,7 +489,7 @@
 static int expiration_struct2str(const void *obj, const intptr_t *args, char **buf)
 {
 	const struct ast_sip_contact *contact = obj;
-	return (ast_asprintf(buf, "%ld", contact->expiration_time.tv_sec) < 0) ? -1 : 0;
+	return (ast_asprintf(buf, "%" TIME_T_FMT, TIME_T_CAST(contact->expiration_time.tv_sec)) < 0) ? -1 : 0;
 }
 
 static int permanent_uri_sort_fn(const void *obj_left, const void *obj_right, int flags)
diff --git a/res/res_pjsip/pjsip_options.c b/res/res_pjsip/pjsip_options.c
index e1f048e..5f60a54 100644
--- a/res/res_pjsip/pjsip_options.c
+++ b/res/res_pjsip/pjsip_options.c
@@ -2733,7 +2733,7 @@
 	ast_str_append(&buf, 0, "AOR: %s\r\n", wrapper->aor_id);
 	ast_str_append(&buf, 0, "URI: %s\r\n", contact->uri);
 	ast_str_append(&buf, 0, "UserAgent: %s\r\n", contact->user_agent);
-	ast_str_append(&buf, 0, "RegExpire: %ld\r\n", contact->expiration_time.tv_sec);
+	ast_str_append(&buf, 0, "RegExpire: %" TIME_T_FMT "\r\n", TIME_T_CAST(contact->expiration_time.tv_sec));
 	if (!ast_strlen_zero(contact->via_addr)) {
 		ast_str_append(&buf, 0, "ViaAddress: %s", contact->via_addr);
 		if (contact->via_port) {
diff --git a/res/res_pjsip_history.c b/res/res_pjsip_history.c
index de1063b..9f01328 100644
--- a/res/res_pjsip_history.c
+++ b/res/res_pjsip_history.c
@@ -198,12 +198,15 @@
 	/* Used for timeval */
 	{
 		struct timeval right = { 0, };
+		long long llv;
 
-		if (sscanf(op_right->field, "%ld", &right.tv_sec) != 1) {
+		if (sscanf(op_right->field, "%" TIME_T_FMT, &llv) != 1) {
 			ast_log(LOG_WARNING, "Unable to extract field '%s': not a timestamp\n", op_right->field);
 			return -1;
 		}
 
+		right.tv_sec = llv;
+
 		return ast_tvcmp(*(struct timeval *)op_left, right) == 0;
 	}
 	case OPT_SOCKADDR_T:
@@ -269,12 +272,15 @@
 	/* Used for timeval */
 	{
 		struct timeval right = { 0, };
+		long long llv;
 
-		if (sscanf(op_right->field, "%ld", &right.tv_sec) != 1) {
+		if (sscanf(op_right->field, "%" TIME_T_FMT, &llv) != 1) {
 			ast_log(LOG_WARNING, "Unable to extract field '%s': not a timestamp\n", op_right->field);
 			return -1;
 		}
 
+		right.tv_sec = llv;
+
 		return ast_tvcmp(*(struct timeval *)op_left, right) == -1;
 	}
 	default:
@@ -318,12 +324,15 @@
 	/* Used for timeval */
 	{
 		struct timeval right = { 0, };
+		long long llv;
 
-		if (sscanf(op_right->field, "%ld", &right.tv_sec) != 1) {
+		if (sscanf(op_right->field, "%" TIME_T_FMT, &llv) != 1) {
 			ast_log(LOG_WARNING, "Unable to extract field '%s': not a timestamp\n", op_right->field);
 			return -1;
 		}
 
+		right.tv_sec = llv;
+
 		return ast_tvcmp(*(struct timeval *)op_left, right) == 1;
 	}
 	default:
@@ -668,18 +677,18 @@
 		char uri[128];
 
 		pjsip_uri_print(PJSIP_URI_IN_REQ_URI, entry->msg->line.req.uri, uri, sizeof(uri));
-		snprintf(line, len, "%-5.5d %-10.10ld %-5.5s %-24.24s %.*s %s SIP/2.0",
+		snprintf(line, len, "%-5.5d %-10.10" TIME_T_FMT " %-5.5s %-24.24s %.*s %s SIP/2.0",
 			entry->number,
-			entry->timestamp.tv_sec,
+			TIME_T_CAST(entry->timestamp.tv_sec),
 			entry->transmitted ? "* ==>" : "* <==",
 			addr,
 			(int)pj_strlen(&entry->msg->line.req.method.name),
 			pj_strbuf(&entry->msg->line.req.method.name),
 			uri);
 	} else {
-		snprintf(line, len, "%-5.5d %-10.10ld %-5.5s %-24.24s SIP/2.0 %u %.*s",
+		snprintf(line, len, "%-5.5d %-10.10" TIME_T_FMT " %-5.5s %-24.24s SIP/2.0 %u %.*s",
 			entry->number,
-			entry->timestamp.tv_sec,
+			TIME_T_CAST(entry->timestamp.tv_sec),
 			entry->transmitted ? "* ==>" : "* <==",
 			addr,
 			entry->msg->line.status.code,
@@ -1169,11 +1178,11 @@
 		pj_sockaddr_print(&entry->src, addr, sizeof(addr), 3);
 	}
 
-	ast_cli(a->fd, "<--- History Entry %d %s %s at %-10.10ld --->\n",
+	ast_cli(a->fd, "<--- History Entry %d %s %s at %-10.10" TIME_T_FMT " --->\n",
 		entry->number,
 		entry->transmitted ? "Sent to" : "Received from",
 		addr,
-		entry->timestamp.tv_sec);
+		TIME_T_CAST(entry->timestamp.tv_sec));
 	ast_cli(a->fd, "%s\n", buf);
 
 	ast_free(buf);
diff --git a/res/res_pjsip_pubsub.c b/res/res_pjsip_pubsub.c
index dae3fef..1d53960 100644
--- a/res/res_pjsip_pubsub.c
+++ b/res/res_pjsip_pubsub.c
@@ -4771,7 +4771,7 @@
 static int persistence_expires_struct2str(const void *obj, const intptr_t *args, char **buf)
 {
 	const struct subscription_persistence *persistence = obj;
-	return (ast_asprintf(buf, "%ld", persistence->expires.tv_sec) < 0) ? -1 : 0;
+	return (ast_asprintf(buf, "%" TIME_T_FMT, TIME_T_CAST(persistence->expires.tv_sec)) < 0) ? -1 : 0;
 }
 
 #define RESOURCE_LIST_INIT_SIZE 4
diff --git a/res/res_pjsip_registrar.c b/res/res_pjsip_registrar.c
index 9c999c1..c12f244 100644
--- a/res/res_pjsip_registrar.c
+++ b/res/res_pjsip_registrar.c
@@ -1370,7 +1370,7 @@
 	while (check_interval) {
 		sleep(check_interval);
 
-		sprintf(time, "%ld", ast_tvnow().tv_sec);
+		sprintf(time, "%" TIME_T_FMT, TIME_T_CAST(ast_tvnow().tv_sec));
 		var = ast_variable_new("expiration_time <=", time, "");
 
 		ast_debug(4, "Woke up at %s  Interval: %d\n", time, check_interval);
diff --git a/res/res_stir_shaken.c b/res/res_stir_shaken.c
index 373a1a1..12c38b6 100644
--- a/res/res_stir_shaken.c
+++ b/res/res_stir_shaken.c
@@ -389,7 +389,7 @@
 		actual_expires.tv_sec += EXPIRATION_BUFFER;
 	}
 
-	snprintf(time_buf, sizeof(time_buf), "%30lu", actual_expires.tv_sec);
+	snprintf(time_buf, sizeof(time_buf), "%30" TIME_T_FMT, TIME_T_CAST(actual_expires.tv_sec));
 
 	ast_db_put(hash, "expiration", time_buf);
 }

-- 
To view, visit https://gerrit.asterisk.org/c/asterisk/+/18205
To unsubscribe, or for help writing mail filters, visit https://gerrit.asterisk.org/settings

Gerrit-Project: asterisk
Gerrit-Branch: 19
Gerrit-Change-Id: Ic8d61b26033f5c486b917e738c9608b0923a844e
Gerrit-Change-Number: 18205
Gerrit-PatchSet: 1
Gerrit-Owner: Philip Prindeville <philipp at redfish-solutions.com>
Gerrit-CC: Sebastian Kemper <sebastian_ml at gmx.net>
Gerrit-MessageType: newchange
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.digium.com/pipermail/asterisk-code-review/attachments/20220307/d0fd3a82/attachment-0001.html>


More information about the asterisk-code-review mailing list