Enhancement #750 » 0014-sanitize-null-writes-write-errors-oversized-integers.patch
| src/connection.c | ||
|---|---|---|
| 
     	size = sizeof(char)*strlen(message); 
   | 
||
| 
     	// let's not ERR (SSL_write doesn't allow 0 len writes) 
   | 
||
| 
     	if (size == 0) 
   | 
||
| 
     		return WRITE_OK; 
   | 
||
| 
     	// this will fail anyways 
   | 
||
| 
     	if (size > INT_MAX) { 
   | 
||
| 
     		mylog(LOG_ERROR, "Message too long in SSL write_socket"); 
   | 
||
| 
     		return WRITE_ERROR; 
   | 
||
| 
     	} 
   | 
||
| 
     	if (!cn->client && cn->cert == NULL) { 
   | 
||
| 
     		cn->cert = mySSL_get_cert(cn->ssl_h); 
   | 
||
| 
     		if (cn->cert == NULL) { 
   | 
||
| ... | ... | |
| 
     			return WRITE_ERROR; 
   | 
||
| 
     		} 
   | 
||
| 
     	} 
   | 
||
| 
     	count = SSL_write(cn->ssl_h, (const void *)message, size); 
   | 
||
| 
     	count = SSL_write(cn->ssl_h, (const void *)message, (int)size); 
   | 
||
| 
     	ERR_print_errors(errbio); 
   | 
||
| 
     	if (count <= 0) { 
   | 
||
| 
     		int err = SSL_get_error(cn->ssl_h, count); 
   | 
||
| ... | ... | |
| 
     		} 
   | 
||
| 
     		return WRITE_ERROR; 
   | 
||
| 
     	} 
   | 
||
| 
     	if (count != size) { 
   | 
||
| 
     	if (count != (int)size) { 
   | 
||
| 
     		/* abnormal : openssl keeps writing until message is not fully 
   | 
||
| 
     		 * sent */ 
   | 
||
| 
     		mylog(LOG_DEBUG, "only %d written while message length is %d", 
   | 
||
| 
     		mylog(LOG_ERROR, "SSL_write wrote only %d while message length is %d", 
   | 
||
| 
     				count,size); 
   | 
||
| 
     	} 
   | 
||
| ... | ... | |
| 
     /* returns 1 if connection must be notified */ 
   | 
||
| 
     static int read_socket_SSL(connection_t *cn) 
   | 
||
| 
     { 
   | 
||
| 
     	int max, count; 
   | 
||
| 
     	int count; 
   | 
||
| 
     	size_t max; 
   | 
||
| 
     	if (cn == NULL) 
   | 
||
| 
     		return 0; 
   | 
||
| 
     	if (cn->incoming_end >= CONN_BUFFER_SIZE) { 
   | 
||
| 
     		mylog(LOG_ERROR, "read_socket_SSL: internal error"); 
   | 
||
| 
     		return -1; 
   | 
||
| 
     	} 
   | 
||
| 
     	max = sizeof(char)*(CONN_BUFFER_SIZE - cn->incoming_end); 
   | 
||
| 
     	if (max > INT_MAX) { 
   | 
||
| 
     		mylog(LOG_ERROR, "read_socket_SSL: cannot read that much data"); 
   | 
||
| 
     		return -1; 
   | 
||
| 
     	} 
   | 
||
| 
     	max = CONN_BUFFER_SIZE - cn->incoming_end; 
   | 
||
| 
     	if (!cn->client && cn->cert == NULL) { 
   | 
||
| 
     		cn->cert = mySSL_get_cert(cn->ssl_h); 
   | 
||
| 
     		if (cn->cert == NULL) { 
   | 
||
| ... | ... | |
| 
     			return -1; 
   | 
||
| 
     		} 
   | 
||
| 
     	} 
   | 
||
| 
     	count = SSL_read(cn->ssl_h, (void *)cn->incoming + cn->incoming_end, 
   | 
||
| 
     			sizeof(char) * max); 
   | 
||
| 
     	count = SSL_read(cn->ssl_h, (void *)(cn->incoming + cn->incoming_end), 
   | 
||
| 
     			(int)max); 
   | 
||
| 
     	ERR_print_errors(errbio); 
   | 
||
| 
     	if (count < 0) { 
   | 
||
| 
     		int err = SSL_get_error(cn->ssl_h, count); 
   | 
||
| ... | ... | |
| 
     			connection_close(cn); 
   | 
||
| 
     		} 
   | 
||
| 
     		return 1; 
   | 
||
| 
     	} else { 
   | 
||
| 
     		cn->incoming_end += (size_t)count; 
   | 
||
| 
     		return 0; 
   | 
||
| 
     	} 
   | 
||
| 
     	cn->incoming_end += count; 
   | 
||
| 
     	return 0; 
   | 
||
| 
     } 
   | 
||
| 
     #endif 
   | 
||
| 
     /* returns 1 if connection must be notified */ 
   | 
||
| 
     static int read_socket(connection_t *cn) 
   | 
||
| 
     { 
   | 
||
| 
     	int max, count; 
   | 
||
| 
     	ssize_t count; 
   | 
||
| 
     	size_t max; 
   | 
||
| 
     	if (cn == NULL) 
   | 
||
| 
     		return 0; 
   | 
||
| 
     	max = CONN_BUFFER_SIZE - cn->incoming_end; 
   | 
||
| 
     	count = read(cn->handle, cn->incoming+cn->incoming_end, 
   | 
||
| 
     			sizeof(char)*max); 
   | 
||
| 
     	if (cn->incoming_end >= CONN_BUFFER_SIZE) { 
   | 
||
| 
     		mylog(LOG_ERROR, "read_socket: internal error"); 
   | 
||
| 
     		return -1; 
   | 
||
| 
     	} 
   | 
||
| 
     	max = sizeof(char)*(CONN_BUFFER_SIZE - cn->incoming_end); 
   | 
||
| 
     	count = read(cn->handle, cn->incoming+cn->incoming_end, max); 
   | 
||
| 
     	if (count < 0) { 
   | 
||
| 
     		if (errno == EAGAIN || errno == EINTR || errno == EINPROGRESS) 
   | 
||
| 
     			return 0; 
   | 
||
| ... | ... | |
| 
     			connection_close(cn); 
   | 
||
| 
     		} 
   | 
||
| 
     		return 1; 
   | 
||
| 
     	} else { 
   | 
||
| 
     		cn->incoming_end += (unsigned)count; 
   | 
||
| 
     		return 0; 
   | 
||
| 
     	} 
   | 
||
| 
     	cn->incoming_end += count; 
   | 
||
| 
     	return 0; 
   | 
||
| 
     } 
   | 
||
| 
     static void data_find_lines(connection_t *cn) 
   | 
||
| src/connection.h | ||
|---|---|---|
| 
     	time_t connect_time; 
   | 
||
| 
     	time_t timeout; 
   | 
||
| 
     	char *incoming; 
   | 
||
| 
     	unsigned incoming_end; 
   | 
||
| 
     	size_t incoming_end; 
   | 
||
| 
     	list_t *outgoing; 
   | 
||
| 
     	char *partial; 
   | 
||
| 
     	list_t *incoming_lines; 
   | 
||
| src/irc.c | ||
|---|---|---|
| 
     	} 
   | 
||
| 
     	/* LINK(src) == LINK(dest) */ 
   | 
||
| 
     	size_t len = strlen(irc_line_elem(line, 2)) + 5; 
   | 
||
| 
     	size_t len = strlen(irc_line_elem(line, 2)) + 6; 
   | 
||
| 
     	// snprintf fix                               ^ 
   | 
||
| 
     	// ‘__builtin___snprintf_chk’ output may be truncated before the last format character 
   | 
||
| 
     	char *tmp; 
   | 
||
| 
     	if (len == 0) 
   | 
||
| ... | ... | |
| 
     static int bip_get_index(const char* str, char car) 
   | 
||
| 
     { 
   | 
||
| 
     	char *cur; 
   | 
||
| 
     	if ((cur = strchr(str, car))) 
   | 
||
| 
     		return cur - str + 1; 
   | 
||
| 
     	else 
   | 
||
| 
     	long diff; 
   | 
||
| 
     	if (!(cur = strchr(str, car))) 
   | 
||
| 
     		return 0; 
   | 
||
| 
     	diff = cur - str + 1; 
   | 
||
| 
     	if (diff > INT_MAX) 
   | 
||
| 
     		fatal("bip_get_index: string too long"); 
   | 
||
| 
     	return (int)diff; 
   | 
||
| 
     } 
   | 
||
| 
     static int bip_fls(long v) 
   | 
||
| src/log.c | ||
|---|---|---|
| 
     static char *_log_wrap(const char *dest, const char *line) 
   | 
||
| 
     { 
   | 
||
| 
     	char *buf; 
   | 
||
| 
     	size_t count; 
   | 
||
| 
     	int count; 
   | 
||
| 
     	buf = bip_malloc((size_t)LOGLINE_MAXLEN + 1); 
   | 
||
| 
     	count = snprintf(buf, (size_t)LOGLINE_MAXLEN + 1, 
   | 
||
| 
     			":" P_IRCMASK " PRIVMSG %s :%s\r\n", dest, line); 
   | 
||
| 
     	if (count < 0) { 
   | 
||
| 
     		mylog(LOG_ERROR, "_log_wrap: error on snprintf: %s", 
   | 
||
| 
     				strerror(errno)); 
   | 
||
| 
     		buf[LOGLINE_MAXLEN - 2] = '\r'; 
   | 
||
| 
     		buf[LOGLINE_MAXLEN - 1] = '\n'; 
   | 
||
| 
     		buf[LOGLINE_MAXLEN] = 0; 
   | 
||
| 
     		return buf; 
   | 
||
| 
     	} 
   | 
||
| 
     	if (count >= LOGLINE_MAXLEN + 1) { 
   | 
||
| 
     		mylog(LOG_DEBUG, "line too long"); 
   | 
||
| 
     		mylog(LOG_WARN, "_log_wrap: line too long"); 
   | 
||
| 
     		buf[LOGLINE_MAXLEN - 2] = '\r'; 
   | 
||
| 
     		buf[LOGLINE_MAXLEN - 1] = '\n'; 
   | 
||
| 
     		buf[LOGLINE_MAXLEN] = 0; 
   | 
||
| ... | ... | |
| 
     void log_write(log_t *logdata, const char *destination, const char *str) 
   | 
||
| 
     { 
   | 
||
| 
     	logstore_t *store = log_find_file(logdata, destination); 
   | 
||
| 
     	size_t written; 
   | 
||
| 
     	if (!store) { 
   | 
||
| 
     		mylog(LOG_ERROR, "Unable to find/create logfile for '%s'", 
   | 
||
| 
     				destination); 
   | 
||
| 
     		return; 
   | 
||
| 
     	} 
   | 
||
| 
     	_log_write(logdata, store, destination, str); 
   | 
||
| 
     	written = _log_write(logdata, store, destination, str); 
   | 
||
| 
     	if (written <= 0) 
   | 
||
| 
     		mylog(LOG_WARN, "log_write to '%s' failed", destination); 
   | 
||
| 
     } 
   | 
||
| 
     static list_t *log_all_logs = NULL; 
   | 
||