Fix con_puts buffer overread

ASan reports a 2K read from a small string literal.

Also, fix silly double copy in con_add_buffer_line and delete too-short
memset in con_add_buffer_line.
This commit is contained in:
Kp 2013-12-17 23:30:39 +00:00
parent 779d1b95db
commit a40c19f770
2 changed files with 21 additions and 14 deletions

View file

@ -3,6 +3,8 @@
#ifndef _CONSOLE_H_
#define _CONSOLE_H_
#include <cstddef>
#include <cstring>
#include "pstypes.h"
#include "dxxsconf.h"
#include "fmtcheck.h"
@ -20,7 +22,7 @@
#define CON_LINES_ONSCREEN 18
#define CON_SCROLL_OFFSET (CON_LINES_ONSCREEN - 3)
#define CON_LINES_MAX 128
#define CON_LINE_LENGTH 2048
static const size_t CON_LINE_LENGTH = 2048;
#define CON_STATE_OPEN 2
#define CON_STATE_OPENING 1
@ -34,7 +36,16 @@ typedef struct console_buffer
} __pack__ console_buffer;
void con_init(void);
void con_puts(int level, const char *str) __attribute_nonnull();
void con_puts(int level, const char *str, size_t len) __attribute_nonnull();
static inline void con_puts(int level, const char *str)
{
con_puts(level, str, strlen(str));
}
template <size_t len>
static inline void con_puts(int level, const char (&str)[len])
{
con_puts(level, str, len - 1);
}
void con_printf(int level, const char *fmt, ...) __attribute_format_printf(2, 3);
#define con_printf(A1,F,...) dxx_call_printf_checked(con_printf,con_puts,(A1),(F),##__VA_ARGS__)
void con_showup(void);

View file

@ -4,6 +4,7 @@
*
*/
#include <algorithm>
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
@ -25,7 +26,7 @@ static PHYSFS_file *gamelog_fp=NULL;
static struct console_buffer con_buffer[CON_LINES_MAX];
static int con_state = CON_STATE_CLOSED, con_scroll_offset = 0, con_size = 0;
static void con_add_buffer_line(int priority, const char *buffer)
static void con_add_buffer_line(int priority, const char *buffer, size_t len)
{
int i=0;
@ -35,14 +36,11 @@ static void con_add_buffer_line(int priority, const char *buffer)
con_buffer[i-1].priority=con_buffer[i].priority;
memcpy(&con_buffer[i-1].line,&con_buffer[i].line,CON_LINE_LENGTH);
}
memset(con_buffer[CON_LINES_MAX-1].line,'\0',sizeof(CON_LINE_LENGTH));
con_buffer[CON_LINES_MAX-1].priority=priority;
memcpy(&con_buffer[CON_LINES_MAX-1].line,buffer,CON_LINE_LENGTH);
for (i=0; i<CON_LINE_LENGTH; i++)
{
con_buffer[CON_LINES_MAX-1].line[i]=buffer[i];
}
size_t copy = std::min(len, CON_LINE_LENGTH - 1);
memcpy(&con_buffer[CON_LINES_MAX-1].line,buffer, copy);
con_buffer[CON_LINES_MAX-1].line[copy] = 0;
}
void (con_printf)(int priority, const char *fmt, ...)
@ -50,8 +48,6 @@ void (con_printf)(int priority, const char *fmt, ...)
va_list arglist;
char buffer[CON_LINE_LENGTH];
memset(buffer,'\0',CON_LINE_LENGTH);
if (priority <= ((int)GameArg.DbgVerbose))
{
char *p1, *p2;
@ -76,16 +72,16 @@ void (con_printf)(int priority, const char *fmt, ...)
}
while (*p1);
*p2 = 0;
con_puts(priority, buffer);
con_puts(priority, buffer, p2 - buffer);
}
}
void con_puts(int priority, const char *buffer)
void con_puts(int priority, const char *buffer, size_t len)
{
if (priority <= ((int)GameArg.DbgVerbose))
{
/* add given string to con_buffer */
con_add_buffer_line(priority, buffer);
con_add_buffer_line(priority, buffer, len);
/* Print output to stdout */
puts(buffer);