LOG: change qb_vsprintf_serialize() into qb_vsnprintf_serialize()

This is to prevent overwriting the ringbuffer.
Also remove stpcpy() as it is not used anymore.

Signed-off-by: Angus Salkeld <asalkeld@redhat.com>
This commit is contained in:
Angus Salkeld 2012-08-29 21:40:40 +10:00
parent 8820724f59
commit a55554efb1
7 changed files with 90 additions and 66 deletions

View File

@ -200,7 +200,7 @@ AM_CONDITIONAL(HAVE_KQUEUE,
[test "x$ac_cv_func_kqueue" = xyes])
AC_CONFIG_LIBOBJ_DIR(lib)
AC_REPLACE_FUNCS(strlcpy strlcat strchrnul stpcpy)
AC_REPLACE_FUNCS(strlcpy strlcat strchrnul)
## local defines
PACKAGE_FEATURES=""

View File

@ -162,10 +162,6 @@ size_t strlcpy(char *dest, const char *src, size_t maxlen);
size_t strlcat(char *dest, const char *src, size_t maxlen);
#endif
#ifndef HAVE_STPCPY
char * stpcpy(char *dest, const char *src);
#endif
#ifndef PATH_MAX
#define PATH_MAX 4096
#endif

View File

@ -95,11 +95,13 @@ _blackbox_vlogger(int32_t target,
chunk += sizeof(uint32_t);
/* log message */
msg_len = qb_vsprintf_serialize(chunk, cs->format, ap);
if(msg_len > QB_LOG_MAX_LEN) {
msg_len = qb_vsnprintf_serialize(chunk, QB_LOG_MAX_LEN, cs->format, ap);
if(msg_len >= QB_LOG_MAX_LEN) {
chunk = msg_len_pt + sizeof(uint32_t); /* Reset */
msg_len = qb_vsprintf_serialize(chunk, "Log message too long to be stored in the blackbox. Maximum is QB_LOG_MAX_LEN" , ap);
msg_len = qb_vsnprintf_serialize(chunk, QB_LOG_MAX_LEN,
"Log message too long to be stored in the blackbox. "\
"Maximum is QB_LOG_MAX_LEN" , ap);
actual_size += msg_len;
}

View File

@ -379,18 +379,16 @@ qb_log_target_format(int32_t target,
}
size_t
qb_vsprintf_serialize(char *serialize, const char *fmt, va_list ap)
qb_vsnprintf_serialize(char *serialize, size_t max_len,
const char *fmt, va_list ap)
{
char *format;
char *p;
uint32_t location = 0;
int type_long = 0;
int type_longlong = 0;
int sformat_length = 0;
int sformat_precision = 0;
p = stpcpy(serialize, fmt);
location = p - serialize + 1;
uint32_t location = strlcpy(serialize, fmt, max_len) + 1;
format = (char *)fmt;
for (;;) {
@ -433,6 +431,9 @@ reprocess:
goto reprocess;
case '*': /* variable field width, save */ {
int arg_int = va_arg(ap, int);
if (location + sizeof (int) > max_len) {
return max_len;
}
memcpy(&serialize[location], &arg_int, sizeof (int));
location += sizeof(int);
format++;
@ -456,6 +457,9 @@ reprocess:
if (type_long) {
long int arg_int;
if (location + sizeof (long int) > max_len) {
return max_len;
}
arg_int = va_arg(ap, long int);
memcpy(&serialize[location], &arg_int,
sizeof(long int));
@ -465,6 +469,9 @@ reprocess:
} else if (type_longlong) {
long long int arg_int;
if (location + sizeof (long long int) > max_len) {
return max_len;
}
arg_int = va_arg(ap, long long int);
memcpy(&serialize[location], &arg_int,
sizeof(long long int));
@ -474,6 +481,9 @@ reprocess:
} else {
int arg_int;
if (location + sizeof (int) > max_len) {
return max_len;
}
arg_int = va_arg(ap, int);
memcpy(&serialize[location], &arg_int,
sizeof(int));
@ -492,6 +502,9 @@ reprocess:
{
double arg_double;
if (location + sizeof (double) > max_len) {
return max_len;
}
arg_double = va_arg(ap, double);
memcpy (&serialize[location], &arg_double, sizeof (double));
location += sizeof(double);
@ -503,6 +516,9 @@ reprocess:
int arg_int;
unsigned char arg_char;
if (location + sizeof (unsigned int) > max_len) {
return max_len;
}
arg_int = va_arg(ap, unsigned int);
arg_char = (unsigned char)arg_int;
memcpy (&serialize[location], &arg_char, sizeof (unsigned char));
@ -514,24 +530,38 @@ reprocess:
char *arg_string;
arg_string = va_arg(ap, char *);
if (arg_string == NULL) {
p = stpcpy(&serialize[location], "(null)");
location += strlcpy(&serialize[location],
"(null)",
QB_MIN(strlen("(null)") + 1,
max_len - location));
} else if (sformat_length) {
p = stpncpy(&serialize[location], arg_string, sformat_length);
serialize[location+sformat_length] = 0;
location += strlcpy(&serialize[location],
arg_string,
QB_MIN(sformat_length + 1,
(max_len - location)));
} else {
p = stpcpy(&serialize[location], arg_string);
location += strlcpy(&serialize[location],
arg_string,
QB_MIN(strlen(arg_string) + 1,
max_len - location));
}
location += p - &serialize[location] + 1;
location++;
break;
}
case 'p':
{
ptrdiff_t arg_pointer = va_arg(ap, ptrdiff_t);
if (location + sizeof (ptrdiff_t) > max_len) {
return max_len;
}
memcpy(&serialize[location], &arg_pointer, sizeof(ptrdiff_t));
location += sizeof(ptrdiff_t);
break;
}
case '%':
if (location + 1 > max_len) {
return max_len;
}
serialize[location++] = '%';
sformat_length = 0;
sformat_precision = 0;
@ -558,14 +588,15 @@ qb_vsnprintf_deserialize(char *string, size_t str_len, const char *buf)
int type_longlong = 0;
int len;
string[0] = '\0';
format = (char *)buf;
for (;;) {
type_long = 0;
type_longlong = 0;
p = strchrnul((const char *)format, '%');
if (*p == '\0') {
p = stpcpy(&string[location], format);
location += p - &string[location] + 1;
location = strlcat(&string[location], format, str_len) + 1;
p += location;
break;
}
/* copy from current to the next % */

View File

@ -95,7 +95,7 @@ struct qb_log_callsite *qb_log_dcs_get(int32_t *newly_created,
uint32_t tags);
const char * qb_log_priority2str(uint8_t priority);
size_t qb_vsprintf_serialize(char *serialize, const char *fmt, va_list ap);
size_t qb_vsnprintf_serialize(char *serialize, size_t max_len, const char *fmt, va_list ap);
size_t qb_vsnprintf_deserialize(char *string, size_t str_len, const char *buf);
void qb_log_target_format_static(int32_t target, const char * format, char *output_buffer);

View File

@ -1,38 +0,0 @@
/* stpcpy.c -- copy a string and return pointer to end of new string
Copyright (C) 1992, 1995, 1997-1998, 2006, 2009-2012 Free Software
Foundation, Inc.
NOTE: The canonical source of this file is maintained with the GNU C Library.
Bugs can be reported to bug-glibc@prep.ai.mit.edu.
This program is free software: you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as published by the
Free Software Foundation; either version 2.1 of the License, or any
later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
#include <config.h>
#include <string.h>
/* Copy SRC to DEST, returning the address of the terminating '\0' in DEST. */
char *
stpcpy (char *dest, const char *src)
{
register char *d = dest;
register const char *s = src;
do
*d++ = *s;
while (*s++ != '\0');
return d - 1;
}

View File

@ -29,7 +29,7 @@
#include <qb/qbutil.h>
#include <qb/qblog.h>
extern size_t qb_vsprintf_serialize(char *serialize, const char *fmt, va_list ap);
extern size_t qb_vsnprintf_serialize(char *serialize, size_t max_len, const char *fmt, va_list ap);
extern size_t qb_vsnprintf_deserialize(char *string, size_t strlen, const char *buf);
@ -40,11 +40,22 @@ format_this(char *out, const char *fmt, ...)
va_list ap;
va_start(ap, fmt);
qb_vsprintf_serialize(buf, fmt, ap);
qb_vsnprintf_serialize(buf, QB_LOG_MAX_LEN, fmt, ap);
qb_vsnprintf_deserialize(out, QB_LOG_MAX_LEN, buf);
va_end(ap);
}
static void
format_this_up_to(char *out, size_t max_len, const char *fmt, ...)
{
char buf[QB_LOG_MAX_LEN];
va_list ap;
va_start(ap, fmt);
qb_vsnprintf_serialize(buf, max_len, fmt, ap);
qb_vsnprintf_deserialize(out, QB_LOG_MAX_LEN, buf);
va_end(ap);
}
START_TEST(test_va_serialize)
{
@ -89,6 +100,9 @@ START_TEST(test_va_serialize)
format_this(buf, ":%*d:", 8, 96);
ck_assert_str_eq(buf, ": 96:");
format_this_up_to(buf, 11, "123456789____");
ck_assert_str_eq(buf, "123456789_");
}
END_TEST
@ -559,12 +573,31 @@ END_TEST
START_TEST(test_log_long_msg)
{
qb_log_init("test", LOG_USER, LOG_DEBUG);
qb_log_filter_ctl(QB_LOG_SYSLOG, QB_LOG_FILTER_ADD,
QB_LOG_FILTER_FILE, "*", LOG_DEBUG);
qb_log_format_set(QB_LOG_SYSLOG, "%b");
int lpc;
int rc;
int i, max = 1000;
char *buffer = calloc(1, max);
qb_log(LOG_ERR, "QMF Agent Initialized: broker=localhost:49000 interval=5 storeFile=.cloudpolicyengine-data-cpe name=cloudpolicyengine.org:cpe:04eabb39-89cf-47dd-9d14-7e77d864be07 QMF Agent Initialized: broker=localhost:49000 interval=5 storeFile=.cloudpolicyengine-data-cpe name=cloudpolicyengine.org:cpe:04eabb39-89cf-47dd-9d14-7e77d864be07 QMF Agent Initialized: broker=localhost:49000 interval=5 storeFile=.cloudpolicyengine-data-cpe name=cloudpolicyengine.org:cpe:04eabb39-89cf-47dd-9d14-7e77d864be07");
qb_log_init("test", LOG_USER, LOG_DEBUG);
rc = qb_log_ctl(QB_LOG_SYSLOG, QB_LOG_CONF_ENABLED, QB_FALSE);
ck_assert_int_eq(rc, 0);
rc = qb_log_ctl(QB_LOG_BLACKBOX, QB_LOG_CONF_SIZE, 1024);
ck_assert_int_eq(rc, 0);
rc = qb_log_ctl(QB_LOG_BLACKBOX, QB_LOG_CONF_ENABLED, QB_TRUE);
ck_assert_int_eq(rc, 0);
rc = qb_log_filter_ctl(QB_LOG_BLACKBOX, QB_LOG_FILTER_ADD,
QB_LOG_FILTER_FILE, "*", LOG_TRACE);
ck_assert_int_eq(rc, 0);
for (lpc = 500; lpc < max; lpc++) {
lpc++;
for(i = 0; i < max; i++) {
buffer[i] = 'a' + (i % 10);
}
buffer[lpc%600] = 0;
qb_log(LOG_INFO, "Message %d %d - %s", lpc, lpc%600, buffer);
}
qb_log_fini();
}
END_TEST