enhanced qse_addtime() and qse_subtime() to detect overflow/underflow
changed qse_mbsntonwad()/qse_wcsntonwad() to accept a unix path beginning with a slash. changed the nwad to string conversion function to not append @ if a unix socket address begins with a slash
This commit is contained in:
		| @ -93,7 +93,7 @@ | |||||||
| #define QSE_SEC_TO_USEC(sec) ((sec) * QSE_USECS_PER_SEC) | #define QSE_SEC_TO_USEC(sec) ((sec) * QSE_USECS_PER_SEC) | ||||||
| #define QSE_USEC_TO_SEC(usec) ((usec) / QSE_USECS_PER_SEC) | #define QSE_USEC_TO_SEC(usec) ((usec) / QSE_USECS_PER_SEC) | ||||||
|  |  | ||||||
| typedef qse_long_t qse_ntime_sec_t; | typedef qse_int64_t qse_ntime_sec_t; | ||||||
| typedef qse_int32_t qse_ntime_nsec_t; | typedef qse_int32_t qse_ntime_nsec_t; | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  | |||||||
| @ -619,14 +619,64 @@ void qse_addtime (const qse_ntime_t* x, const qse_ntime_t* y, qse_ntime_t* z) | |||||||
| 	QSE_ASSERT (x->nsec >= 0 && x->nsec < QSE_NSECS_PER_SEC); | 	QSE_ASSERT (x->nsec >= 0 && x->nsec < QSE_NSECS_PER_SEC); | ||||||
| 	QSE_ASSERT (y->nsec >= 0 && y->nsec < QSE_NSECS_PER_SEC); | 	QSE_ASSERT (y->nsec >= 0 && y->nsec < QSE_NSECS_PER_SEC); | ||||||
|  |  | ||||||
|  | #if 0 | ||||||
| 	z->sec = x->sec + y->sec; | 	z->sec = x->sec + y->sec; | ||||||
| 	z->nsec = x->nsec + y->nsec; | 	z->nsec = x->nsec + y->nsec; | ||||||
|  |  | ||||||
| 	if (z->nsec >= QSE_NSECS_PER_SEC) | 	while (z->nsec >= QSE_NSECS_PER_SEC) | ||||||
| 	{ | 	{ | ||||||
| 		z->sec = z->sec + 1; | 		z->sec = z->sec + 1; | ||||||
| 		z->nsec = z->nsec - QSE_NSECS_PER_SEC; | 		z->nsec = z->nsec - QSE_NSECS_PER_SEC; | ||||||
| 	} | 	} | ||||||
|  | #else | ||||||
|  | 	qse_ntime_sec_t xs, ys; | ||||||
|  | 	qse_ntime_nsec_t ns; | ||||||
|  |  | ||||||
|  | 	ns = x->nsec + y->nsec; | ||||||
|  | 	if (ns >= QSE_NSECS_PER_SEC) | ||||||
|  | 	{ | ||||||
|  | 		ns = ns - QSE_NSECS_PER_SEC; | ||||||
|  | 		if (x->sec == QSE_TYPE_MAX(qse_ntime_sec_t)) | ||||||
|  | 		{ | ||||||
|  | 			if (y->sec >= 0) goto overflow; | ||||||
|  | 			xs = x->sec; | ||||||
|  | 			ys = y->sec + 1; /* this won't overflow */ | ||||||
|  | 		} | ||||||
|  | 		else | ||||||
|  | 		{ | ||||||
|  | 			xs = x->sec + 1; /* this won't overflow */ | ||||||
|  | 			ys = y->sec; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	else | ||||||
|  | 	{ | ||||||
|  | 		xs = x->sec; | ||||||
|  | 		ys = y->sec; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if ((ys >= 1 && xs > QSE_TYPE_MAX(qse_ntime_sec_t) - ys) || | ||||||
|  | 	    (ys <= -1 && xs < QSE_TYPE_MIN(qse_ntime_sec_t) - ys)) | ||||||
|  | 	{ | ||||||
|  | 		if (xs >= 0) | ||||||
|  | 		{ | ||||||
|  | 		overflow: | ||||||
|  | 			xs = QSE_TYPE_MAX(qse_ntime_sec_t); | ||||||
|  | 			ns = QSE_NSECS_PER_SEC - 1; | ||||||
|  | 		} | ||||||
|  | 		else | ||||||
|  | 		{ | ||||||
|  | 			xs = QSE_TYPE_MIN(qse_ntime_sec_t); | ||||||
|  | 			ns = 0; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	else | ||||||
|  | 	{ | ||||||
|  | 		xs = xs + ys; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	z->sec = xs; | ||||||
|  | 	z->nsec = ns; | ||||||
|  | #endif | ||||||
| } | } | ||||||
|  |  | ||||||
| void qse_subtime (const qse_ntime_t* x, const qse_ntime_t* y, qse_ntime_t* z) | void qse_subtime (const qse_ntime_t* x, const qse_ntime_t* y, qse_ntime_t* z) | ||||||
| @ -634,18 +684,66 @@ void qse_subtime (const qse_ntime_t* x, const qse_ntime_t* y, qse_ntime_t* z) | |||||||
| 	QSE_ASSERT (x->nsec >= 0 && x->nsec < QSE_NSECS_PER_SEC); | 	QSE_ASSERT (x->nsec >= 0 && x->nsec < QSE_NSECS_PER_SEC); | ||||||
| 	QSE_ASSERT (y->nsec >= 0 && y->nsec < QSE_NSECS_PER_SEC); | 	QSE_ASSERT (y->nsec >= 0 && y->nsec < QSE_NSECS_PER_SEC); | ||||||
|  |  | ||||||
|  | #if 0 | ||||||
| 	z->sec = x->sec - y->sec; | 	z->sec = x->sec - y->sec; | ||||||
| 	z->nsec = x->nsec - y->nsec; | 	z->nsec = x->nsec - y->nsec; | ||||||
|  |  | ||||||
| 	if (z->nsec < 0) | 	while (z->nsec < 0) | ||||||
| 	{ | 	{ | ||||||
| 		z->sec = z->sec - 1; | 		z->sec = z->sec - 1; | ||||||
| 		z->nsec = z->nsec + QSE_NSECS_PER_SEC; | 		z->nsec = z->nsec + QSE_NSECS_PER_SEC; | ||||||
| 	} | 	} | ||||||
|  | #else | ||||||
|  | 	qse_ntime_sec_t xs, ys; | ||||||
|  | 	qse_ntime_nsec_t ns; | ||||||
|  |  | ||||||
|  | 	ns = x->nsec - y->nsec; | ||||||
|  | 	if (ns < 0) | ||||||
|  | 	{ | ||||||
|  | 		ns = ns + QSE_NSECS_PER_SEC; | ||||||
|  | 		if (x->sec == QSE_TYPE_MIN(qse_ntime_sec_t)) | ||||||
|  | 		{ | ||||||
|  | 			if (y->sec <= 0) goto underflow; | ||||||
|  | 			xs = x->sec; | ||||||
|  | 			ys = y->sec - 1; /* this won't underflow */ | ||||||
|  | 		} | ||||||
|  | 		else | ||||||
|  | 		{ | ||||||
|  | 			xs = x->sec - 1; /* this won't underflow */ | ||||||
|  | 			ys = y->sec; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	else | ||||||
|  | 	{ | ||||||
|  | 		xs = x->sec; | ||||||
|  | 		ys = y->sec; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if ((ys >= 1 && xs < QSE_TYPE_MIN(qse_ntime_sec_t) + ys) || | ||||||
|  | 	    (ys <= -1 && xs > QSE_TYPE_MAX(qse_ntime_sec_t) + ys)) | ||||||
|  | 	{ | ||||||
|  | 		if (xs >= 0) | ||||||
|  | 		{ | ||||||
|  | 			xs = QSE_TYPE_MAX(qse_ntime_sec_t); | ||||||
|  | 			ns = QSE_NSECS_PER_SEC - 1; | ||||||
|  | 		} | ||||||
|  | 		else | ||||||
|  | 		{ | ||||||
|  | 		underflow: | ||||||
|  | 			xs = QSE_TYPE_MIN(qse_ntime_sec_t); | ||||||
|  | 			ns = 0; | ||||||
|  | 		} | ||||||
|  | 	}  | ||||||
|  | 	else | ||||||
|  | 	{ | ||||||
|  | 		xs = xs - ys; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	z->sec = xs; | ||||||
|  | 	z->nsec = ns; | ||||||
|  | #endif | ||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
| int qse_mbs_to_ntime (const qse_mchar_t* text, qse_ntime_t* ntime) | int qse_mbs_to_ntime (const qse_mchar_t* text, qse_ntime_t* ntime) | ||||||
| { | { | ||||||
| 	const qse_mchar_t* p = text, * cp; | 	const qse_mchar_t* p = text, * cp; | ||||||
|  | |||||||
| @ -356,13 +356,14 @@ int Socket::finiConnectNB () QSE_CPP_NOEXCEPT | |||||||
| { | { | ||||||
| 	QSE_ASSERT (qse_is_sck_valid(this->handle)); | 	QSE_ASSERT (qse_is_sck_valid(this->handle)); | ||||||
|  |  | ||||||
| 	if (qse_fini_sck_conn(this->handle) <= -1) | 	int n; | ||||||
|  | 	if ((n = qse_fini_sck_conn(this->handle)) <= -1) | ||||||
| 	{ | 	{ | ||||||
| 		this->setErrorFmt (syserr_to_errnum(errno), QSE_T("%hs"), strerror(errno)); | 		this->setErrorFmt (syserr_to_errnum(errno), QSE_T("%hs"), strerror(errno)); | ||||||
| 		return -1; | 		return -1; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	return 0; | 	return n; | ||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
| @ -522,6 +523,7 @@ int Socket::accept (Socket* newsck, SocketAddress* newaddr, int traits) QSE_CPP_ | |||||||
|  |  | ||||||
| accept_done: | accept_done: | ||||||
| 	newsck->handle = newfd; | 	newsck->handle = newfd; | ||||||
|  | 	newsck->domain = this->domain; // the new socket inherits the listener's domain. | ||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | |||||||
| @ -289,7 +289,7 @@ int SocketAddress::set (const qse_wchar_t* str, qse_size_t len) QSE_CPP_NOEXCEPT | |||||||
| /*  | /*  | ||||||
|  * NOTICE:  |  * NOTICE:  | ||||||
|  *   When host is "", the address is resolved to localhost. |  *   When host is "", the address is resolved to localhost. | ||||||
|  *   When host is XP_NULL, the address is resolved to INADDR_ANY  |  *   When host is QSE_NULL, the address is resolved to INADDR_ANY  | ||||||
|  *   or IN6ADDR_ANY_INIT depending on the address family. |  *   or IN6ADDR_ANY_INIT depending on the address family. | ||||||
|  */ |  */ | ||||||
| int SocketAddress::resolve (const qse_mchar_t* service, const qse_mchar_t* host, int family, int type) QSE_CPP_NOEXCEPT | int SocketAddress::resolve (const qse_mchar_t* service, const qse_mchar_t* host, int family, int type) QSE_CPP_NOEXCEPT | ||||||
| @ -354,6 +354,7 @@ int SocketAddress::resolve (const qse_wchar_t* service, const qse_wchar_t* host, | |||||||
| 		if (qse_wcstombs(service, &wcslen, mb_service, &mbslen) <= -1) return -1; | 		if (qse_wcstombs(service, &wcslen, mb_service, &mbslen) <= -1) return -1; | ||||||
| 		p_service = mb_service; | 		p_service = mb_service; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	x = ::getaddrinfo(p_host, p_service, &hints, &info);	 | 	x = ::getaddrinfo(p_host, p_service, &hints, &info);	 | ||||||
| 	if (x != 0) return -1; | 	if (x != 0) return -1; | ||||||
| 	 | 	 | ||||||
|  | |||||||
| @ -626,7 +626,7 @@ int qse_mux_insert (qse_mux_t* mux, const qse_mux_evt_t* evt) | |||||||
|  |  | ||||||
| 	if (!mux->me.ptr[evt->hnd]) | 	if (!mux->me.ptr[evt->hnd]) | ||||||
| 	{ | 	{ | ||||||
| 		mux->me.ptr[evt->hnd] = QSE_MMGR_ALLOC (mux->mmgr, QSE_SIZEOF(*evt)); | 		mux->me.ptr[evt->hnd] = QSE_MMGR_ALLOC(mux->mmgr, QSE_SIZEOF(*evt)); | ||||||
| 		if (!mux->me.ptr[evt->hnd]) | 		if (!mux->me.ptr[evt->hnd]) | ||||||
| 		{ | 		{ | ||||||
| 			mux->errnum = QSE_MUX_ENOMEM; | 			mux->errnum = QSE_MUX_ENOMEM; | ||||||
| @ -819,7 +819,7 @@ done: | |||||||
| 		return -1; | 		return -1; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if (epoll_ctl (mux->fd, EPOLL_CTL_DEL, evt->hnd, QSE_NULL) <= -1) | 	if (epoll_ctl(mux->fd, EPOLL_CTL_DEL, evt->hnd, QSE_NULL) <= -1) | ||||||
| 	{ | 	{ | ||||||
| 		mux->errnum = skerr_to_errnum(errno); | 		mux->errnum = skerr_to_errnum(errno); | ||||||
| 		return -1; | 		return -1; | ||||||
|  | |||||||
| @ -135,15 +135,16 @@ int qse_mbsntonwad (const qse_mchar_t* str, qse_size_t len, qse_nwad_t* nwad) | |||||||
|  |  | ||||||
| 	if (p >= end) return -1; | 	if (p >= end) return -1; | ||||||
|  |  | ||||||
| 	if (*p == QSE_MT('@') && len >= 2) | 	if ((*p == '@' && len >= 2) || *p == '/') // with @, you can specify a relative path | ||||||
| 	{ | 	{ | ||||||
| 		/* the string begins with @. it's a local name */ | 		/* the string begins with @. it's a local name excluding @. | ||||||
|  | 		 * if it begins with /, it's also a local name */ | ||||||
| 	#if defined(QSE_CHAR_IS_MCHAR) | 	#if defined(QSE_CHAR_IS_MCHAR) | ||||||
| 		qse_mbsxncpy (tmpad.u.local.path, QSE_COUNTOF(tmpad.u.local.path), p + 1, len - 1); | 		qse_mbsxncpy (tmpad.u.local.path, QSE_COUNTOF(tmpad.u.local.path), p + (*p == '@'), len - (*p == '@')); | ||||||
| 	#else | 	#else | ||||||
| 		qse_size_t mbslen = len - 1; | 		qse_size_t mbslen = len - (*p == '@'); | ||||||
| 		qse_size_t wcslen = QSE_COUNTOF(tmpad.u.local.path) - 1; | 		qse_size_t wcslen = QSE_COUNTOF(tmpad.u.local.path) - 1; | ||||||
| 		if (qse_mbsntowcsn (p + 1, &mbslen, tmpad.u.local.path, &wcslen) <= -1) return -1; | 		if (qse_mbsntowcsn(p + (*p == '@'), &mbslen, tmpad.u.local.path, &wcslen) <= -1) return -1; | ||||||
| 		tmpad.u.local.path[wcslen] = QSE_WT('\0'); | 		tmpad.u.local.path[wcslen] = QSE_WT('\0'); | ||||||
| 	#endif | 	#endif | ||||||
|  |  | ||||||
| @ -317,16 +318,17 @@ int qse_wcsntonwad (const qse_wchar_t* str, qse_size_t len, qse_nwad_t* nwad) | |||||||
|  |  | ||||||
| 	if (p >= end) return -1; | 	if (p >= end) return -1; | ||||||
|  |  | ||||||
| 	if (*p == QSE_WT('@') && len >= 2) | 	if ((*p == '@' && len >= 2) || *p == '/') // with @, you can specify a relative path | ||||||
| 	{ | 	{ | ||||||
| 		/* the string begins with @. it's a local name */ | 		/* the string begins with @. it's a local name excluding @. | ||||||
|  | 		 * if it begins with /, it's also a local name */ | ||||||
| 	#if defined(QSE_CHAR_IS_MCHAR) | 	#if defined(QSE_CHAR_IS_MCHAR) | ||||||
| 		qse_size_t wcslen = len - 1; | 		qse_size_t wcslen = len - 1; | ||||||
| 		qse_size_t mbslen = QSE_COUNTOF(tmpad.u.local.path) - 1; | 		qse_size_t mbslen = QSE_COUNTOF(tmpad.u.local.path) - (*p == '@'); | ||||||
| 		if (qse_wcsntombsn (p + 1, &wcslen, tmpad.u.local.path, &mbslen) <= -1) return -1; | 		if (qse_wcsntombsn(p + (*p == '@'), &wcslen, tmpad.u.local.path, &mbslen) <= -1) return -1; | ||||||
| 		tmpad.u.local.path[mbslen] = QSE_MT('\0'); | 		tmpad.u.local.path[mbslen] = QSE_MT('\0'); | ||||||
| 	#else | 	#else | ||||||
| 		qse_wcsxncpy (tmpad.u.local.path, QSE_COUNTOF(tmpad.u.local.path), p + 1, len - 1); | 		qse_wcsxncpy (tmpad.u.local.path, QSE_COUNTOF(tmpad.u.local.path), p + (*p == '@'), len - (*p == '@')); | ||||||
| 	#endif | 	#endif | ||||||
|  |  | ||||||
| 		tmpad.type = QSE_NWAD_LOCAL; | 		tmpad.type = QSE_NWAD_LOCAL; | ||||||
| @ -583,8 +585,11 @@ qse_size_t qse_nwadtombs ( | |||||||
| 		case QSE_NWAD_LOCAL: | 		case QSE_NWAD_LOCAL: | ||||||
| 			if (flags & QSE_NWADTOMBS_ADDR) | 			if (flags & QSE_NWADTOMBS_ADDR) | ||||||
| 			{ | 			{ | ||||||
| 				if (xlen + 1 >= len) goto done; | 				if (nwad->u.local.path[0] != '/') | ||||||
| 				buf[xlen++] = QSE_MT('@'); | 				{ | ||||||
|  | 					if (xlen + 1 >= len) goto done; | ||||||
|  | 					buf[xlen++] = '@'; | ||||||
|  | 				} | ||||||
|  |  | ||||||
| 			#if defined(QSE_CHAR_IS_MCHAR) | 			#if defined(QSE_CHAR_IS_MCHAR) | ||||||
| 				if (xlen + 1 >= len) goto done; | 				if (xlen + 1 >= len) goto done; | ||||||
| @ -712,8 +717,11 @@ qse_size_t qse_nwadtowcs ( | |||||||
| 		case QSE_NWAD_LOCAL: | 		case QSE_NWAD_LOCAL: | ||||||
| 			if (flags & QSE_NWADTOMBS_ADDR) | 			if (flags & QSE_NWADTOMBS_ADDR) | ||||||
| 			{ | 			{ | ||||||
| 				if (xlen + 1 >= len) goto done; | 				if (nwad->u.local.path[0] != '/') | ||||||
| 				buf[xlen++] = QSE_WT('@'); | 				{ | ||||||
|  | 					if (xlen + 1 >= len) goto done; | ||||||
|  | 					buf[xlen++] = '@'; | ||||||
|  | 				} | ||||||
|  |  | ||||||
| 			#if defined(QSE_CHAR_IS_MCHAR) | 			#if defined(QSE_CHAR_IS_MCHAR) | ||||||
| 				if (xlen + 1 >= len) goto done; | 				if (xlen + 1 >= len) goto done; | ||||||
|  | |||||||
		Reference in New Issue
	
	Block a user