Skip to content

Commit

Permalink
Z: Fix atoe_vsnprintf to support null buffer
Browse files Browse the repository at this point in the history
Std vsnprintf accepts null buffer and returns an estimate
Our implementation does not support that
Updated the atoe_vsnprintf implementation

Signed-off-by: ehsan kiani far ehsan.kianifar@gmail.com
  • Loading branch information
ehsankianifar committed Nov 6, 2023
1 parent 386a708 commit 277973e
Show file tree
Hide file tree
Showing 2 changed files with 112 additions and 90 deletions.
3 changes: 2 additions & 1 deletion fvtest/porttest/omrstrTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1486,7 +1486,8 @@ printToBuffer(struct OMRPortLibrary *portLibrary, BOOLEAN precision, char *buffe
va_list args;

va_start(args, format);
stringLength = atoe_vsnprintf(buffer, bufferLength, format, args);
atoe_vsnprintf(buffer, bufferLength, format, args);
stringLength = strlen(buffer);
va_end(args);

if (stringLength >= 0) {
Expand Down
199 changes: 110 additions & 89 deletions util/a2e/atoe_utils.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
#include <stdio.h>
#include <stdlib.h> /* for malloc() via e2a_string()/a2e_string() */
#include <string.h>
#include <limits.h>

/*
* ======================================================================
Expand All @@ -55,7 +56,7 @@

#define ERROR_RETVAL -1
#define SUCCESS 0
#define CheckRet(x) { if ((x) == ERROR_RETVAL) return ERROR_RETVAL; }
#define CheckRet(x) { if ((x) < 0) return ERROR_RETVAL; }

typedef struct InstanceData {
char *buffer;
Expand All @@ -67,9 +68,9 @@ typedef struct InstanceData {
* description - Print a charater to InstanceData buffer
* parameters - this Structure holding the receiving buffer
* c Character to add to buffer
* returns - int return code, 0 for success
* returns -
*************************************************************************/
static int
static void
pchar(InstanceData *this, int c)
{
#if 0
Expand Down Expand Up @@ -101,11 +102,10 @@ pchar(InstanceData *this, int c)
}
#endif /* 0 */

if (this->buffer >= this->end) {
return ERROR_RETVAL;
if (this->buffer < this->end) {
*this->buffer = c;
}
*this->buffer++ = c;
return SUCCESS;
*this->buffer++;
}

/**************************************************************************
Expand All @@ -115,7 +115,7 @@ pchar(InstanceData *this, int c)
* str String to add to buffer
* left_justify Left justify string flag
* min_width Minimum width of string added to buffer
* precision
* precision Maximum chars to take from the argument
* returns - int return code, 0 for success
*************************************************************************/
static int
Expand All @@ -130,7 +130,7 @@ fstring(InstanceData *this, char *str, int left_justify, int min_width,
return ERROR_RETVAL;
}

for (width = 0; width < precision; width++) {
for (width = 0; (width < precision) || (precision < 0); width++) {
if ('\0' == str[width]) {
break;
}
Expand All @@ -144,19 +144,19 @@ fstring(InstanceData *this, char *str, int left_justify, int min_width,

if (left_justify) {
while (pad_length > 0) {
CheckRet(pchar(this, ' '));
pchar(this, ' ');
pad_length -= 1;
}
}

while (width-- > 0) {
CheckRet(pchar(this, *p));
pchar(this, *p);
p += 1;
}

if (!left_justify) {
while (pad_length > 0) {
CheckRet(pchar(this, ' '));
pchar(this, ' ');
pad_length -= 1;
}
}
Expand All @@ -178,7 +178,6 @@ typedef enum {
* left_justify Left justify number flag
* min_width Minimum number of charaters value will
* occupy
* precision
* zero_pad Pad number with zeros, flag
* returns - int return code, 0 for success
*************************************************************************/
Expand All @@ -191,6 +190,7 @@ fnumber(InstanceData *this, long value, int format_type, int left_justify,
char convert[MAX_DIGITS + 1];
int place = 0;
int pad_length = 0;
int zero_pad_length = 0;
static char digits[] = "0123456789abcdef";
int base = 0;
bool_t caps = FALSE;
Expand Down Expand Up @@ -242,42 +242,49 @@ fnumber(InstanceData *this, long value, int format_type, int left_justify,
} while (uvalue);
convert[place] = 0;

pad_length = min_width - place;
if (pad_length < 0) {
pad_length = 0;
}
if (left_justify) {
if (zero_pad && pad_length > 0) {
if (sign_value) {
CheckRet(pchar(this, sign_value));
--pad_length;
sign_value = 0;
}
while (pad_length > 0) {
CheckRet(pchar(this, '0'));
--pad_length;
}
} else {
while (pad_length > 0) {
CheckRet(pchar(this, ' '));
--pad_length;
}
if (precision > 0) {
zero_pad_length = precision - place;
} else if ((zero_pad == TRUE) && (left_justify == TRUE)) {
zero_pad_length = min_width - place;
if (sign_value) {
zero_pad_length--;
}
}
if (sign_value) {
CheckRet(pchar(this, sign_value));

if (zero_pad_length < 0) {
zero_pad_length = 0;
}

while (place > 0 && --precision >= 0) {
CheckRet(pchar(this, convert[--place]));
pad_length = min_width - (place + zero_pad_length);
if (sign_value) {
pad_length--;
}

if (!left_justify) {
if (left_justify) {
while (pad_length > 0) {
CheckRet(pchar(this, ' '));
pchar(this, ' ');
--pad_length;
}
}

if (sign_value) {
pchar(this, sign_value);
}

while (zero_pad_length > 0) {
pchar(this, '0');
zero_pad_length--;
}

while (place > 0) {
pchar(this, convert[--place]);
}

while (pad_length > 0) {
pchar(this, ' ');
--pad_length;
}

return SUCCESS;
}

Expand All @@ -291,7 +298,6 @@ fnumber(InstanceData *this, long value, int format_type, int left_justify,
* left_justify Left justify number flag
* min_width Minimum number of charaters value will
* occupy
* precision
* zero_pad Pad number with zeros, flag
* returns - int return code, 0 for success
*=======================================================================
Expand All @@ -305,6 +311,7 @@ flongnumber(InstanceData *this, signed long long value, int format_type, int lef
char convert[MAX_DIGITS + 1];
int place = 0;
int pad_length = 0;
int zero_pad_length = 0;
static char digits[] = "0123456789abcdef";
int base = 0;
bool_t caps = FALSE;
Expand Down Expand Up @@ -356,42 +363,49 @@ flongnumber(InstanceData *this, signed long long value, int format_type, int lef
} while (uvalue);
convert[place] = 0;

pad_length = min_width - place;
if (pad_length < 0) {
pad_length = 0;
}
if (left_justify) {
if (zero_pad && pad_length > 0) {
if (sign_value) {
CheckRet(pchar(this, sign_value));
--pad_length;
sign_value = 0;
}
while (pad_length > 0) {
CheckRet(pchar(this, '0'));
--pad_length;
}
} else {
while (pad_length > 0) {
CheckRet(pchar(this, ' '));
--pad_length;
}
if (precision > 0) {
zero_pad_length = precision - place;
} else if ((zero_pad == TRUE) && (left_justify == TRUE)) {
zero_pad_length = min_width - place;
if (sign_value) {
zero_pad_length--;
}
}
if (sign_value) {
CheckRet(pchar(this, sign_value));

if (zero_pad_length < 0) {
zero_pad_length = 0;
}

while (place > 0 && --precision >= 0) {
CheckRet(pchar(this, convert[--place]));
pad_length = min_width - (place + zero_pad_length);
if (sign_value) {
pad_length--;
}

if (!left_justify) {
if (left_justify) {
while (pad_length > 0) {
CheckRet(pchar(this, ' '));
pchar(this, ' ');
--pad_length;
}
}

if (sign_value) {
pchar(this, sign_value);
}

while (zero_pad_length > 0) {
pchar(this, '0');
zero_pad_length--;
}

while (place > 0) {
pchar(this, convert[--place]);
}

while (pad_length > 0) {
pchar(this, ' ');
--pad_length;
}

return SUCCESS;
}

Expand Down Expand Up @@ -422,14 +436,8 @@ atoe_vsnprintf(char *str, size_t count, const char *fmt, va_list args)
if (fmt == NULL) { /*ibm@029013*/
fmt = NULLCHARSTRING; /*ibm@029013*/
} /*ibm@029013*/
if (str == NULL) {
return ERROR_RETVAL;
}
str[0] = '\0';

this.buffer = str;
this.end = str + count - 1;
*this.end = '\0'; /* ensure null-termination in case of failure */
this.end = this.buffer + count;

while ((ch = *fmt++) != 0) {
if (ch == '%') {
Expand All @@ -440,7 +448,7 @@ atoe_vsnprintf(char *str, size_t count, const char *fmt, va_list args)
pattern = fmt - 1; /*ibm@8665*/
left_justify = TRUE;
min_width = 0;
precision = this.end - this.buffer;
precision = -1; /* -1 means unspecified */

next_char:
ch = *fmt++;
Expand Down Expand Up @@ -501,12 +509,12 @@ atoe_vsnprintf(char *str, size_t count, const char *fmt, va_list args)
break;
case 'c':
ch = va_arg(args, int);
CheckRet(pchar(&this, ch));
pchar(&this, ch);
break;
case '%':
CheckRet(pchar(&this, '%'));
pchar(&this, '%');
#if 0 /* J9 CMVC defect 74726 */
CheckRet(pchar(&this, '%')); /*ibm@5203 */
pchar(&this, '%'); /*ibm@5203 */
#endif
break;
case 'd':
Expand Down Expand Up @@ -545,22 +553,29 @@ atoe_vsnprintf(char *str, size_t count, const char *fmt, va_list args)
/* ibm@8665
* Add floating point support for dbl2str & flt2str
*/
char *b;
int len;
char *tempPattern;
size_t freeCap;
double argument;
int requiredSpace;

b = a2e((char *)pattern, fmt - pattern);
tempPattern = a2e((char *)pattern, fmt - pattern);

/* Extract a double from args, this works for both doubles
* and floats,
* NB if we use float for a single precision floating
* point number the result is wrong.
*/
len = sprintf(this.buffer, b, va_arg(args, double));
free(b);
b = e2a_string(this.buffer);
strcpy(this.buffer, b);
free(b);
this.buffer += len;
freeCap = this.end > this.buffer ? this.end - this.buffer : 0;
argument = va_arg(args, double);
requiredSpace = snprintf(this.buffer, freeCap, tempPattern, argument);
free(tempPattern);
CheckRet(requiredSpace);
if ((freeCap > 0) && (requiredSpace > 0)) {
tempPattern = e2a_string(this.buffer);
strcpy(this.buffer, tempPattern);
free(tempPattern);
}
this.buffer += requiredSpace;
}
break;
default:
Expand All @@ -581,11 +596,17 @@ atoe_vsnprintf(char *str, size_t count, const char *fmt, va_list args)
return ERROR_RETVAL;
}
} else {
CheckRet(pchar(&this, ch));
pchar(&this, ch);
}
}
if (count > 0) {
if (this.buffer < this.end) {
*this.buffer = '\0';
} else {
this.end[-1] = '\0';
}
}
*this.buffer = '\0';
return strlen(str);
return this.buffer - str;
}

/* END OF FILE */

0 comments on commit 277973e

Please sign in to comment.