Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Printf: Implement size checked and va_list variants #4683

Merged
merged 2 commits into from May 5, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/main/common/log.c
Expand Up @@ -116,7 +116,7 @@ static void logPrint(const char *buf, size_t size)
static size_t logFormatPrefix(char *buf, const timeMs_t timeMs)
{
// Write timestamp
return tfp_sprintf(buf, LOG_PREFIX, timeMs / 1000, timeMs % 1000);
return tfp_sprintf(buf, LOG_PREFIX, (int)(timeMs / 1000), (int)(timeMs % 1000));
}

static bool logHasOutput(void)
Expand Down
76 changes: 61 additions & 15 deletions src/main/common/printf.c
Expand Up @@ -60,7 +60,7 @@ static void *stdout_putp;

// print bf, padded from left to at least n characters.
// padding is zero ('0') if z!=0, space (' ') otherwise
static int putchw(void *putp, putcf putf, int n, char z, char *bf)
static int putchw(void *putp, const void *end, putcf putf, int n, char z, char *bf)
{
int written = 0;
char fc = z ? '0' : ' ';
Expand All @@ -75,30 +75,49 @@ static int putchw(void *putp, putcf putf, int n, char z, char *bf)
n--;
if (pr == 0) {
while (n-- > 0) {
putf(putp, fc); written++;
if (putp < end) {
putf(putp, fc);
}
written++;
}
}
while ((ch = *bf++)) {
putf(putp, ch); written++;
if (putp < end) {
putf(putp, ch);
}
written++;
}
if (pr == 1) {
while (n-- > 0) {
putf(putp, fc); written++;
if (putp < end) {
putf(putp, fc);
}
written++;
}
}
return written;
}

// retrun number of bytes written
int tfp_format(void *putp, putcf putf, const char *fmt, va_list va)
{
return tfp_nformat(putp, -1, putf, fmt, va);
}

// return number of bytes written
int tfp_nformat(void *putp, int size, void (*putf) (void *, char), const char *fmt, va_list va)
{
char bf[12];
int written = 0;
char ch;

const void *end = size < 0 ? (void*)UINT32_MAX : ((char *)putp + size - 1);

while ((ch = *(fmt++))) {
if (ch != '%') {
putf(putp, ch); written++;
if (putp < end) {
putf(putp, ch);
}
written++;
} else {
char lz = 0;
char pr = 0; // padding at the right?
Expand Down Expand Up @@ -137,7 +156,7 @@ int tfp_format(void *putp, putcf putf, const char *fmt, va_list va)
else
#endif
ui2a(va_arg(va, unsigned int), 10, 0, bf);
written += putchw(putp, putf, w, lz, bf);
written += putchw(putp, end, putf, w, lz, bf);
break;
}
case 'd':{
Expand All @@ -147,7 +166,7 @@ int tfp_format(void *putp, putcf putf, const char *fmt, va_list va)
else
#endif
i2a(va_arg(va, int), bf);
written += putchw(putp, putf, w, lz, bf);
written += putchw(putp, end, putf, w, lz, bf);
break;
}
case 'x':
Expand All @@ -158,23 +177,29 @@ int tfp_format(void *putp, putcf putf, const char *fmt, va_list va)
else
#endif
ui2a(va_arg(va, unsigned int), 16, (ch == 'X'), bf);
written += putchw(putp, putf, w, lz, bf);
written += putchw(putp, end, putf, w, lz, bf);
break;
case 'c':
putf(putp, (char) (va_arg(va, int))); written++;
if (putp < end) {
putf(putp, (char) (va_arg(va, int)));
}
written++;
break;
case 's':
written += putchw(putp, putf, w, 0, va_arg(va, char *));
written += putchw(putp, end, putf, w, 0, va_arg(va, char *));
break;
case '%':
putf(putp, ch); written++;
if (putp < end) {
putf(putp, ch);
}
written++;
break;
case 'n':
*va_arg(va, int*) = written;
break;
case 'f':
ftoa(va_arg(va, double), bf);
written += putchw(putp, putf, w, lz, bf);
written += putchw(putp, end, putf, w, lz, bf);
break;
default:
break;
Expand Down Expand Up @@ -211,12 +236,33 @@ int tfp_sprintf(char *s, const char *fmt, ...)
va_list va;

va_start(va, fmt);
int written = tfp_format(&s, putcp, fmt, va);
putcp(&s, 0);
int written = tfp_vsprintf(s, fmt, va);
va_end(va);
return written;
}

int tfp_snprintf(char *s, int size, const char *fmt, ...)
{
va_list va;

va_start(va, fmt);
int written = tfp_vsnprintf(s, size, fmt, va);
va_end(va);
return written;
}

int tfp_vsprintf(char *s, const char *fmt, va_list va)
{
return tfp_vsnprintf(s, -1, fmt, va);
}

int tfp_vsnprintf(char *s, int size, const char *fmt, va_list va)
{
int written = tfp_nformat(&s, size, putcp, fmt, va);
putcp(&s, 0);
return written;
}


static void _putc(void *p, char c)
{
Expand Down
11 changes: 6 additions & 5 deletions src/main/common/printf.h
Expand Up @@ -109,13 +109,14 @@ regs Kusti, 23.10.2004

void init_printf(void *putp, void (*putf) (void *, char));

int tfp_printf(const char *fmt, ...);
int tfp_sprintf(char *s, const char *fmt, ...);
int tfp_printf(const char *fmt, ...) __attribute__ ((format (printf, 1, 2)));
int tfp_sprintf(char *s, const char *fmt, ...) __attribute__ ((format (printf, 2, 3)));
int tfp_snprintf(char *s, int size, const char *fmt, ...) __attribute__ ((format (printf, 3, 4)));
int tfp_vsprintf(char *s, const char *fmt, va_list va) __attribute__ ((format (printf, 2, 0)));
int tfp_vsnprintf(char *s, int size, const char *fmt, va_list va) __attribute__ ((format (printf, 3, 0)));

int tfp_format(void *putp, void (*putf) (void *, char), const char *fmt, va_list va);

#define printf tfp_printf
#define sprintf tfp_sprintf
int tfp_nformat(void *putp, int n, void (*putf) (void *, char), const char *fmt, va_list va);

void printfSupportInit(void);
struct serialPort_s;
Expand Down
14 changes: 7 additions & 7 deletions src/main/fc/cli.c
Expand Up @@ -864,7 +864,7 @@ static void cliSerialPassthrough(char *cmdline)
serialPortUsage_t *passThroughPortUsage = findSerialPortUsageByIdentifier(id);
if (!passThroughPortUsage || passThroughPortUsage->serialPort == NULL) {
if (!baud) {
printf("Port %d is closed, must specify baud.\r\n", id);
tfp_printf("Port %d is closed, must specify baud.\r\n", id);
return;
}
if (!mode)
Expand All @@ -874,29 +874,29 @@ static void cliSerialPassthrough(char *cmdline)
baud, mode,
SERIAL_NOT_INVERTED);
if (!passThroughPort) {
printf("Port %d could not be opened.\r\n", id);
tfp_printf("Port %d could not be opened.\r\n", id);
return;
}
printf("Port %d opened, baud = %d.\r\n", id, baud);
tfp_printf("Port %d opened, baud = %u.\r\n", id, (unsigned)baud);
} else {
passThroughPort = passThroughPortUsage->serialPort;
// If the user supplied a mode, override the port's mode, otherwise
// leave the mode unchanged. serialPassthrough() handles one-way ports.
printf("Port %d already open.\r\n", id);
tfp_printf("Port %d already open.\r\n", id);
if (mode && passThroughPort->mode != mode) {
printf("Adjusting mode from %d to %d.\r\n",
tfp_printf("Adjusting mode from %d to %d.\r\n",
passThroughPort->mode, mode);
serialSetMode(passThroughPort, mode);
}
// If this port has a rx callback associated we need to remove it now.
// Otherwise no data will be pushed in the serial port buffer!
if (passThroughPort->rxCallback) {
printf("Removing rxCallback\r\n");
tfp_printf("Removing rxCallback\r\n");
passThroughPort->rxCallback = 0;
}
}

printf("Forwarding data to %d, power cycle to exit.\r\n", id);
tfp_printf("Forwarding data to %d, power cycle to exit.\r\n", id);

serialPassthrough(cliPort, passThroughPort, NULL, NULL);
}
Expand Down
6 changes: 3 additions & 3 deletions src/main/io/dashboard.c
Expand Up @@ -367,7 +367,7 @@ static void showStatusPage(void)

if (feature(FEATURE_CURRENT_METER)) {
i2c_OLED_set_line(rowIndex++);
tfp_sprintf(lineBuffer, "mAh: %d", getMAhDrawn());
tfp_sprintf(lineBuffer, "mAh: %d", (int)getMAhDrawn());
padLineBufferToChar(12);
i2c_OLED_send_string(lineBuffer);

Expand All @@ -392,7 +392,7 @@ static void showStatusPage(void)
i2c_OLED_set_line(rowIndex++);
i2c_OLED_send_string(lineBuffer);

tfp_sprintf(lineBuffer, "La/Lo: %d/%d", gpsSol.llh.lat / GPS_DEGREES_DIVIDER, gpsSol.llh.lon / GPS_DEGREES_DIVIDER);
tfp_sprintf(lineBuffer, "La/Lo: %d/%d", (int)(gpsSol.llh.lat / GPS_DEGREES_DIVIDER), (int)(gpsSol.llh.lon / GPS_DEGREES_DIVIDER));
padLineBuffer();
i2c_OLED_set_line(rowIndex++);
i2c_OLED_send_string(lineBuffer);
Expand All @@ -412,7 +412,7 @@ static void showStatusPage(void)
#ifdef USE_BARO
if (sensors(SENSOR_BARO)) {
int32_t alt = baroCalculateAltitude();
tfp_sprintf(lineBuffer, "Alt: %d", alt / 100);
tfp_sprintf(lineBuffer, "Alt: %d", (int)(alt / 100));
padHalfLineBuffer();
i2c_OLED_set_xy(HALF_SCREEN_CHARACTER_COLUMN_COUNT, rowIndex);
i2c_OLED_send_string(lineBuffer);
Expand Down
2 changes: 1 addition & 1 deletion src/main/io/ledstrip.c
Expand Up @@ -338,7 +338,7 @@ void generateLedConfig(ledConfig_t *ledConfig, char *ledConfigBuffer, size_t buf
*fptr = 0;

// TODO - check buffer length
sprintf(ledConfigBuffer, "%u,%u:%s:%s:%u", ledGetX(ledConfig), ledGetY(ledConfig), directions, baseFunctionOverlays, ledGetColor(ledConfig));
tfp_sprintf(ledConfigBuffer, "%u,%u:%s:%s:%u", ledGetX(ledConfig), ledGetY(ledConfig), directions, baseFunctionOverlays, ledGetColor(ledConfig));
}

typedef enum {
Expand Down