Skip to content

Commit

Permalink
Move NULL check to ocrpt_format_string() from ocrpt_format() and ocrp…
Browse files Browse the repository at this point in the history
…t_dtosf()

This way, when the format string has literals around the format
specifier, the literals are printed.

It also fixes a crash when the printf() function is used in
report expressions with NULL data.

Adapted the unit test ocrpt_expr_format_test to exercise NULLs
and NULLs with the wrong data type for the format specifier.

Signed-off-by: Zoltán Böszörményi <[email protected]>
  • Loading branch information
zboszor committed May 9, 2022
1 parent b180a97 commit 9970b73
Show file tree
Hide file tree
Showing 4 changed files with 51 additions and 35 deletions.
45 changes: 24 additions & 21 deletions libsrc/formatting.c
Original file line number Diff line number Diff line change
Expand Up @@ -767,15 +767,14 @@ void ocrpt_format_string(opencreport *o, ocrpt_expr *e, const char *formatstring
goto end_inner_loop;
break;
case OCRPT_FORMAT_NUMBER:
if (mpfr_asprintf(&result, tmp->str, data->number) >= 0) {
if (!data->isnull && mpfr_asprintf(&result, tmp->str, data->number) >= 0) {
ocrpt_mem_string_append(string, result);
mpfr_free_str(result);
}
data_handled = true;
break;
case OCRPT_FORMAT_MONEY:
len = ocrpt_mpfr_strfmon(o, NULL, 0, tmp->str, data->number);
if (len >= 0) {
if (!data->isnull && (len = ocrpt_mpfr_strfmon(o, NULL, 0, tmp->str, data->number)) >= 0) {
result = ocrpt_mem_malloc(len + 1);
ocrpt_mpfr_strfmon(o, result, len, tmp->str, data->number);
result[len] = 0;
Expand All @@ -785,35 +784,39 @@ void ocrpt_format_string(opencreport *o, ocrpt_expr *e, const char *formatstring
data_handled = true;
break;
case OCRPT_FORMAT_DATETIME:
char dt[256];
if (!data->isnull) {
char dt[256];

strftime_l(dt, sizeof(dt), tmp->str, &data->datetime, o->locale);
ocrpt_mem_string_append(string, dt);
strftime_l(dt, sizeof(dt), tmp->str, &data->datetime, o->locale);
ocrpt_mem_string_append(string, dt);
}
data_handled = true;
break;
case OCRPT_FORMAT_STRING:
int32_t blen = data->string->len;
if (!data->isnull) {
int32_t blen = data->string->len;

if (length > 0) {
int32_t slen;
ocrpt_utf8forward(data->string->str, length, &slen, data->string->len, &blen);
if (length > 0) {
int32_t slen;
ocrpt_utf8forward(data->string->str, length, &slen, data->string->len, &blen);

if (lpadded) {
char *padstr;
int32_t padlen;
if (lpadded) {
char *padstr;
int32_t padlen;

padlen = length - slen;
padstr = ocrpt_mem_malloc(padlen + 1);
memset(padstr, ' ', padlen);
padstr[padlen] = 0;
padlen = length - slen;
padstr = ocrpt_mem_malloc(padlen + 1);
memset(padstr, ' ', padlen);
padstr[padlen] = 0;

ocrpt_mem_string_append(string, padstr);
ocrpt_mem_string_append(string, padstr);

ocrpt_mem_free(padstr);
ocrpt_mem_free(padstr);
}
}
}

ocrpt_mem_string_append_len(string, data->string->str, blen);
ocrpt_mem_string_append_len(string, data->string->str, blen);
}
data_handled = true;
break;
case OCRPT_FORMAT_NONE:
Expand Down
14 changes: 0 additions & 14 deletions libsrc/functions.c
Original file line number Diff line number Diff line change
Expand Up @@ -3602,13 +3602,6 @@ OCRPT_STATIC_FUNCTION(ocrpt_format) {

ocrpt_expr_init_result(o, e, OCRPT_RESULT_STRING);

/* If the data to be formatted is NULL, it is treated as an empty string. */
if (e->ops[0]->result[o->residx]->isnull) {
e->result[o->residx]->string->str[0] = 0;
e->result[o->residx]->string->len = 0;
return;
}

char *formatstring = NULL;
int32_t formatlen = 0;

Expand Down Expand Up @@ -3682,13 +3675,6 @@ OCRPT_STATIC_FUNCTION(ocrpt_dtosf) {

ocrpt_expr_init_result(o, e, OCRPT_RESULT_STRING);

/* If the data to be formatted is NULL, it is treated as an empty string. */
if (e->ops[0]->result[o->residx]->isnull) {
e->result[o->residx]->string->str[0] = 0;
e->result[o->residx]->string->len = 0;
return;
}

/*
* Result would be garbage for intervals.
* Let's return an empty string.
Expand Down
14 changes: 14 additions & 0 deletions tests/expected/ocrpt_expr_format_test.stdout
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,20 @@ expr optimized: (string)You had 6 apples on 2022-05-01 and 2 oranges on 2022-05-
expr nodes: 1
(string)You had 6 apples on 2022-05-01 and 2 oranges on 2022-05-02 in your pocket.

string: printf('You had %d %s on !@{%Y-%m-%d} and %d %s on !@{%Y-%m-%d} in your pocket.', nulln(), nulls(), nulldt(), nulln(), nulls(), nulldt())
expr reprinted: printf((string)You had %d %s on !@{%Y-%m-%d} and %d %s on !@{%Y-%m-%d} in your pocket.,nulln(),nulls(),nulldt(),nulln(),nulls(),nulldt())
expr nodes: 8
expr optimized: (string)You had on and on in your pocket.
expr nodes: 1
(string)You had on and on in your pocket.

string: printf('You had %d %s on !@{%Y-%m-%d} and %d %s on !@{%Y-%m-%d} in your pocket.', nulln(), nulls(), nulldt(), nulln(), nulls(), nulls())
expr reprinted: printf((string)You had %d %s on !@{%Y-%m-%d} and %d %s on !@{%Y-%m-%d} in your pocket.,nulln(),nulls(),nulldt(),nulln(),nulls(),nulls())
expr nodes: 8
expr optimized: (ERROR)format error
expr nodes: 1
(ERROR)format error

string: format('apples and oranges', '%6.3d')
expr reprinted: format((string)apples and oranges,(string)%6.3d)
expr nodes: 3
Expand Down
13 changes: 13 additions & 0 deletions tests/ocrpt_expr_format_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,19 @@ int main(void) {

"printf('You had %d %s on !@{%Y-%m-%d} and %d %s on !@{%Y-%m-%d} in your pocket.', 6, 'apples', stodt('2022-05-01'), 2, 'oranges', stodt('2022-05-02'))",

/*
* NULL data is treated as empty string,
* regardless of the optional width specifier.
* Literals from the format string are printed as is.
*/
"printf('You had %d %s on !@{%Y-%m-%d} and %d %s on !@{%Y-%m-%d} in your pocket.', nulln(), nulls(), nulldt(), nulln(), nulls(), nulldt())",

/*
* This will throw a "format error".
* Data has a type first, then the data may be NULL.
*/
"printf('You had %d %s on !@{%Y-%m-%d} and %d %s on !@{%Y-%m-%d} in your pocket.', nulln(), nulls(), nulldt(), nulln(), nulls(), nulls())",

/* Invalid formats */

/* Numeric format for a string */
Expand Down

0 comments on commit 9970b73

Please sign in to comment.