Skip to content

Commit

Permalink
FIXED: Possible memory leak in various C API functions using ``BUF_MA…
Browse files Browse the repository at this point in the history
…LLOC``

These functions could "stack" intermediate results, overflowing the
string stack when used excessively inside a single foreign predicate
or outside calls from Prolog (i.e., using "main" in foreign code).
  • Loading branch information
JanWielemaker committed Oct 7, 2024
1 parent 3458401 commit 1beb59e
Show file tree
Hide file tree
Showing 2 changed files with 70 additions and 54 deletions.
15 changes: 14 additions & 1 deletion src/os/pl-text.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
Author: Jan Wielemaker and Anjo Anjewierden
E-mail: [email protected]
WWW: http://www.swi-prolog.org
Copyright (c) 2011-2022, University of Amsterdam
Copyright (c) 2011-2024, University of Amsterdam
VU University Amsterdam
SWI-Prolog Solutions b.v.
All rights reserved.
Expand Down Expand Up @@ -138,4 +138,17 @@ text_chr(const PL_chars_t *t, int chr)
return (size_t)-1;
}

/*******************************
* STRING BUFFERS *
*******************************/

#define PL_STRINGS_MARK_IF_MALLOC(flags) \
{ buf_mark_t __PL_mark; \
if ( flags&BUF_MALLOC ) \
PL_mark_string_buffers(&__PL_mark);
#define PL_STRINGS_RELEASE_IF_MALLOC(flags) \
if ( flags&BUF_MALLOC ) \
PL_release_string_buffers_from_mark(__PL_mark); \
}

#endif /*PL_TEXT_H_INCLUDED*/
109 changes: 56 additions & 53 deletions src/pl-fli.c
Original file line number Diff line number Diff line change
Expand Up @@ -1130,12 +1130,19 @@ _PL_cvt_i_char(term_t p, char *c, int mn, int mx)
if ( PL_get_integer(p, &i) && i >= mn && i <= mx )
{ *c = (char)i;
return true;
} else if ( PL_get_text(p, &txt, CVT_ATOM|CVT_STRING|CVT_LIST) )
{ if ( txt.length == 1 && txt.encoding == ENC_ISO_LATIN_1 )
} else
{ bool rc;
PL_STRINGS_MARK();
if ( PL_get_text(p, &txt, CVT_ATOM|CVT_STRING|CVT_LIST) &&
txt.length == 1 && txt.encoding == ENC_ISO_LATIN_1 )
{ *c = txt.text.t[0];
return true; /* can never be allocated */
rc = true; /* can never be allocated */
} else
{ rc = false;
}
PL_free_text(&txt);
PL_STRINGS_RELEASE();
if ( rc )
return true;
}

if ( PL_is_integer(p) )
Expand Down Expand Up @@ -1732,9 +1739,10 @@ PL_get_atom_nchars(term_t t, size_t *len, char **s)
bool
PL_atom_mbchars(atom_t a, size_t *len, char **s, unsigned int flags)
{ PL_chars_t text;
bool rc;

valid_atom_t(a);
if ( !get_atom_text(a, &text) )
if ( !get_atom_text(a, &text) ) /* always PL_CHARS_HEAP */
{ if ( (flags&CVT_EXCEPTION) )
{ term_t t;
return ((t = PL_new_term_ref()) &&
Expand All @@ -1744,19 +1752,18 @@ PL_atom_mbchars(atom_t a, size_t *len, char **s, unsigned int flags)
return false;
}

if ( PL_mb_text(&text, flags) )
{ PL_save_text(&text, flags);
PL_STRINGS_MARK_IF_MALLOC(flags);
rc = ( PL_mb_text(&text, flags) &&
PL_save_text(&text, flags) );
PL_STRINGS_RELEASE_IF_MALLOC(flags);

if ( len )
if ( rc )
{ if ( len )
*len = text.length;
*s = text.text.t;

return true;
} else
{ PL_free_text(&text);

return false;
}

return rc;
}


Expand Down Expand Up @@ -1819,50 +1826,45 @@ bool
PL_get_wchars(term_t l, size_t *length, pl_wchar_t **s, unsigned flags)
{ GET_LD
PL_chars_t text;
buf_mark_t mark;
bool rc;

valid_term_t(l);
if ( (flags&BUF_MALLOC) )
PL_mark_string_buffers(&mark);

if ( !PL_get_text(l, &text, flags) )
return false;
PL_promote_text(&text);
PL_save_text(&text, flags);

if ( (flags&BUF_MALLOC) )
PL_release_string_buffers_from_mark(mark);

if ( length )
*length = text.length;
*s = text.text.w;
PL_STRINGS_MARK_IF_MALLOC(flags);
rc = ( PL_get_text(l, &text, flags) &&
PL_promote_text(&text) &&
PL_save_text(&text, flags) );
PL_STRINGS_RELEASE_IF_MALLOC(flags);

if ( rc )
{ if ( length )
*length = text.length;
*s = text.text.w;
}

return true;
return rc;
}


bool
PL_get_nchars(term_t l, size_t *length, char **s, unsigned flags)
{ GET_LD
PL_chars_t text;
bool rc;

valid_term_t(l);
if ( !PL_get_text(l, &text, flags) )
return false;

if ( PL_mb_text(&text, flags) )
{ PL_save_text(&text, flags);

if ( length )
PL_STRINGS_MARK_IF_MALLOC(flags);
rc = ( PL_get_text(l, &text, flags) &&
PL_mb_text(&text, flags) &&
PL_save_text(&text, flags) );
PL_STRINGS_RELEASE_IF_MALLOC(flags);

if ( rc )
{ if ( length )
*length = text.length;
*s = text.text.t;

return true;
} else
{ PL_free_text(&text);

return false;
}

return rc;
}


Expand All @@ -1878,23 +1880,24 @@ PL_get_text_as_atom(term_t t, atom_t *a, int flags)
valid_term_t(t);
word w = valHandle(t);
PL_chars_t text;
atom_t ta;
bool rc;

if ( isAtom(w) )
{ *a = (atom_t) w;
return true;
}

if ( PL_get_text(t, &text, flags) )
{ atom_t ta = textToAtom(&text);

PL_free_text(&text);
if ( ta )
{ *a = ta;
return true;
}
}
PL_STRINGS_MARK();
if ( PL_get_text(t, &text, flags) &&
(ta=textToAtom(&text)) )
{ *a = ta;
rc = true;
} else
rc = false;
PL_STRINGS_RELEASE();

return false;
return rc;
}


Expand Down

0 comments on commit 1beb59e

Please sign in to comment.