Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,23 @@
# monolix2rx 0.0.7

* Fixed implicit `ptrdiff_t` to `int` truncation in `rc_dup_str` (`src/shared.c`);
pointer differences are now range-checked before conversion to `int`.

* Fixed potential integer overflow in all 13 `trans_*` parser entry-points: the
`strlen(gBuf)` result is now checked against `INT_MAX` before being cast to
`int` for the `dparse()` call.

* Fixed signed integer overflow in `sbuf` size arithmetic (`src/sbuf.c`):
`sAppendN`, `sAppend`, and `addLine` now guard against overflow before
computing reallocation sizes.

* Fixed `int col` overflow in `getLine` (`src/parseSyntaxErrors.h`): the column
accumulator is now `size_t` with an explicit bounds check before use.

* Added thread-safety comment to `src/shared.c` documenting that the global
parser state is intentionally not mutex-protected, consistent with R's
single-threaded execution model.

# monolix2rx 0.0.6

* Updated to add types for rstudio completion
Expand Down
8 changes: 7 additions & 1 deletion src/dataSettings.c
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,13 @@ void trans_data_settings(const char* parse){
errP = curP;
eBufLast = 0;
gBufFree=0;
_pn= dparse(curP, gBuf, (int)strlen(gBuf));
{
size_t _gBuf_len = strlen(gBuf);
if (_gBuf_len > (size_t)INT_MAX) {
Rf_error(_("input too large to parse (exceeds INT_MAX bytes)"));
}
_pn= dparse(curP, gBuf, (int)_gBuf_len);
}
if (!_pn || curP->syntax_errors) {
} else {
wprint_parsetree_data_settings(parser_tables_dataSettings , _pn, 0, wprint_node_data_settings, NULL);
Expand Down
8 changes: 7 additions & 1 deletion src/equation.c
Original file line number Diff line number Diff line change
Expand Up @@ -526,7 +526,13 @@ void trans_equation(const char* parse){
errP = curP;
eBufLast = 0;
gBufFree=0;
_pn= dparse(curP, gBuf, (int)strlen(gBuf));
{
size_t _gBuf_len = strlen(gBuf);
if (_gBuf_len > (size_t)INT_MAX) {
Rf_error(_("input too large to parse (exceeds INT_MAX bytes)"));
}
_pn= dparse(curP, gBuf, (int)_gBuf_len);
}
if (!_pn || curP->syntax_errors) {
} else {
wprint_parsetree_equation(parser_tables_equation , _pn, 0, wprint_node_equation, NULL);
Expand Down
8 changes: 7 additions & 1 deletion src/longDef.c
Original file line number Diff line number Diff line change
Expand Up @@ -549,7 +549,13 @@ void trans_longdef(const char* parse){
errP = curP;
eBufLast = 0;
gBufFree=0;
_pn= dparse(curP, gBuf, (int)strlen(gBuf));
{
size_t _gBuf_len = strlen(gBuf);
if (_gBuf_len > (size_t)INT_MAX) {
Rf_error(_("input too large to parse (exceeds INT_MAX bytes)"));
}
_pn= dparse(curP, gBuf, (int)_gBuf_len);
}
if (!_pn || curP->syntax_errors) {
} else {
wprint_parsetree_longdef(parser_tables_longDef , _pn, 0, wprint_node_longdef, NULL);
Expand Down
8 changes: 7 additions & 1 deletion src/longOutput.c
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,13 @@ void trans_longoutput(const char* parse){
errP = curP;
eBufLast = 0;
gBufFree=0;
_pn= dparse(curP, gBuf, (int)strlen(gBuf));
{
size_t _gBuf_len = strlen(gBuf);
if (_gBuf_len > (size_t)INT_MAX) {
Rf_error(_("input too large to parse (exceeds INT_MAX bytes)"));
}
_pn= dparse(curP, gBuf, (int)_gBuf_len);
}
if (!_pn || curP->syntax_errors) {
} else {
wprint_parsetree_longoutput(parser_tables_longOutput , _pn, 0, wprint_node_longoutput, NULL);
Expand Down
8 changes: 7 additions & 1 deletion src/mlxtranContent.c
Original file line number Diff line number Diff line change
Expand Up @@ -369,7 +369,13 @@ void trans_content(const char* parse){
errP = curP;
eBufLast = 0;
gBufFree=0;
_pn= dparse(curP, gBuf, (int)strlen(gBuf));
{
size_t _gBuf_len = strlen(gBuf);
if (_gBuf_len > (size_t)INT_MAX) {
Rf_error(_("input too large to parse (exceeds INT_MAX bytes)"));
}
_pn= dparse(curP, gBuf, (int)_gBuf_len);
}
if (!_pn || curP->syntax_errors) {
} else {
wprint_parsetree_content(parser_tables_mlxtranContent , _pn, 0, wprint_node_content, NULL);
Expand Down
8 changes: 7 additions & 1 deletion src/mlxtranFileinfo.c
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,13 @@ void trans_fileinfo(const char* parse){
errP = curP;
eBufLast = 0;
gBufFree=0;
_pn= dparse(curP, gBuf, (int)strlen(gBuf));
{
size_t _gBuf_len = strlen(gBuf);
if (_gBuf_len > (size_t)INT_MAX) {
Rf_error(_("input too large to parse (exceeds INT_MAX bytes)"));
}
_pn= dparse(curP, gBuf, (int)_gBuf_len);
}
if (!_pn || curP->syntax_errors) {
} else {
wprint_parsetree_fileinfo(parser_tables_mlxtranFileinfo , _pn, 0, wprint_node_fileinfo, NULL);
Expand Down
8 changes: 7 additions & 1 deletion src/mlxtranFit.c
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,13 @@ void trans_fit(const char* parse){
errP = curP;
eBufLast = 0;
gBufFree=0;
_pn= dparse(curP, gBuf, (int)strlen(gBuf));
{
size_t _gBuf_len = strlen(gBuf);
if (_gBuf_len > (size_t)INT_MAX) {
Rf_error(_("input too large to parse (exceeds INT_MAX bytes)"));
}
_pn= dparse(curP, gBuf, (int)_gBuf_len);
}
if (!_pn || curP->syntax_errors) {
} else {
wprint_parsetree_fit(parser_tables_mlxtranFit , _pn, 0, wprint_node_fit, NULL);
Expand Down
8 changes: 7 additions & 1 deletion src/mlxtranInd.c
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,13 @@ void trans_individual(const char* parse){
errP = curP;
eBufLast = 0;
gBufFree=0;
_pn= dparse(curP, gBuf, (int)strlen(gBuf));
{
size_t _gBuf_len = strlen(gBuf);
if (_gBuf_len > (size_t)INT_MAX) {
Rf_error(_("input too large to parse (exceeds INT_MAX bytes)"));
}
_pn= dparse(curP, gBuf, (int)_gBuf_len);
}
if (!_pn || curP->syntax_errors) {
} else {
wprint_parsetree_individual(parser_tables_mlxtranInd , _pn, 0, wprint_node_individual, NULL);
Expand Down
8 changes: 7 additions & 1 deletion src/mlxtranIndDefinition.c
Original file line number Diff line number Diff line change
Expand Up @@ -280,7 +280,13 @@ void trans_indDef(const char* parse){
errP = curP;
eBufLast = 0;
gBufFree=0;
_pn= dparse(curP, gBuf, (int)strlen(gBuf));
{
size_t _gBuf_len = strlen(gBuf);
if (_gBuf_len > (size_t)INT_MAX) {
Rf_error(_("input too large to parse (exceeds INT_MAX bytes)"));
}
_pn= dparse(curP, gBuf, (int)_gBuf_len);
}
if (!_pn || curP->syntax_errors) {
} else {
wprint_parsetree_indDef(parser_tables_mlxtranIndDefinition , _pn, 0, wprint_node_indDef, NULL);
Expand Down
8 changes: 7 additions & 1 deletion src/mlxtranOp.c
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,13 @@ void trans_mlxtran_op(const char* parse){
errP = curP;
eBufLast = 0;
gBufFree=0;
_pn= dparse(curP, gBuf, (int)strlen(gBuf));
{
size_t _gBuf_len = strlen(gBuf);
if (_gBuf_len > (size_t)INT_MAX) {
Rf_error(_("input too large to parse (exceeds INT_MAX bytes)"));
}
_pn= dparse(curP, gBuf, (int)_gBuf_len);
}
if (!_pn || curP->syntax_errors) {
} else {
wprint_parsetree_mlxtran_op(parser_tables_mlxtranOp , _pn, 0, wprint_node_mlxtran_op, NULL);
Expand Down
8 changes: 7 additions & 1 deletion src/mlxtranParameter.c
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,13 @@ void trans_parameter(const char* parse){
errP = curP;
eBufLast = 0;
gBufFree=0;
_pn= dparse(curP, gBuf, (int)strlen(gBuf));
{
size_t _gBuf_len = strlen(gBuf);
if (_gBuf_len > (size_t)INT_MAX) {
Rf_error(_("input too large to parse (exceeds INT_MAX bytes)"));
}
_pn= dparse(curP, gBuf, (int)_gBuf_len);
}
if (!_pn || curP->syntax_errors) {
} else {
wprint_parsetree_parameter(parser_tables_mlxtranParameter , _pn, 0, wprint_node_parameter, NULL);
Expand Down
8 changes: 7 additions & 1 deletion src/mlxtranTask.c
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,13 @@ void trans_mlxtrantask(const char* parse){
errP = curP;
eBufLast = 0;
gBufFree=0;
_pn= dparse(curP, gBuf, (int)strlen(gBuf));
{
size_t _gBuf_len = strlen(gBuf);
if (_gBuf_len > (size_t)INT_MAX) {
Rf_error(_("input too large to parse (exceeds INT_MAX bytes)"));
}
_pn= dparse(curP, gBuf, (int)_gBuf_len);
}
if (!_pn || curP->syntax_errors) {
} else {
wprint_parsetree_mlxtrantask(parser_tables_mlxtranTask , _pn, 0, wprint_node_mlxtrantask, NULL);
Expand Down
16 changes: 12 additions & 4 deletions src/parseSyntaxErrors.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,21 @@
#define syntaxErrorExtra monolix2rx_syntaxErrorExtra

static inline char *getLine (char *src, int line, int *lloc) {
int cur = 1, col=0, i;
int cur = 1, i;
size_t col = 0;
for(i = 0; src[i] != '\0' && cur != line; i++){
if(src[i] == '\n') cur++;
}
for(col = 0; src[i + col] != '\n' && src[i + col] != '\0'; col++);
*lloc=i+col;
char *buf = R_Calloc(col + 1, char);
for(col = 0; src[i + col] != '\n' && src[i + col] != '\0'; col++){
if (col == (size_t)INT_MAX) {
Rf_error(_("line too long in getLine"));
}
}
if ((size_t)i + col > (size_t)INT_MAX) {
Rf_error(_("source offset overflow in getLine"));
}
*lloc = i + (int)col;
char *buf = R_Calloc((int)col + 1, char);
memcpy(buf, src + i, col);
buf[col] = '\0';
return buf;
Expand Down
13 changes: 13 additions & 0 deletions src/sbuf.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@ void sFreeIni(sbuf *sbb) {

void sAppendN(sbuf *sbb, const char *what, int n) {
if (sbb->sN == 0) sIni(sbb);
if (n < 0) Rf_error(_("invalid negative length in sAppendN"));
if (sbb->o > INT_MAX - 2 - n - SBUF_MXBUF) {
Rf_error(_("buffer size overflow in sAppendN"));
}
if (sbb->sN <= 2 + n + sbb->o){
int mx = sbb->o + 2 + n + SBUF_MXBUF;
sbb->s = R_Realloc(sbb->s, mx, char);
Expand All @@ -51,6 +55,9 @@ void sAppend(sbuf *sbb, const char *format, ...) {
n = vsnprintf(zero, 0, format, copy) + 1;
#endif
va_end(copy);
if (n > 0 && sbb->o > INT_MAX - n - 1 - SBUF_MXBUF) {
Rf_error(_("buffer size overflow in sAppend"));
}
if (sbb->sN <= sbb->o + n + 1) {
int mx = sbb->o + n + 1 + SBUF_MXBUF;
sbb->s = R_Realloc(sbb->s, mx, char);
Expand Down Expand Up @@ -109,6 +116,9 @@ void addLine(vLines *sbb, const char *format, ...) {
Rf_errorcall(R_NilValue, _("encoding error in 'addLine' format: '%s' n: %d; errno: %d"), format, n, errno);
}
va_end(copy);
if (sbb->sN > INT_MAX - n - 2 - SBUF_MXBUF) {
Rf_error(_("buffer size overflow in addLine (string buffer)"));
}
if (sbb->sN <= sbb->o + n){
int mx = sbb->sN + n + 2 + SBUF_MXBUF;
sbb->s = R_Realloc(sbb->s, mx, char);
Expand All @@ -121,6 +131,9 @@ void addLine(vLines *sbb, const char *format, ...) {
}
vsnprintf(sbb->s + sbb->o, sbb->sN - sbb->o, format, argptr);
va_end(argptr);
if (sbb->nL > INT_MAX - n - 2 - SBUF_MXLINE) {
Rf_error(_("line array size overflow in addLine"));
}
if (sbb->n + 2 >= sbb->nL){
int mx = sbb->nL + n + 2 + SBUF_MXLINE;
sbb->lProp = R_Realloc(sbb->lProp, mx, int);
Expand Down
20 changes: 18 additions & 2 deletions src/shared.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ dparserPtrIni
#include "parseSyntaxErrors.h"

// These are the shared variables
// NOTE: These globals are intentionally not mutex-protected.
// R's interpreter is single-threaded; its memory allocator (R_Calloc, R_Free)
// and error handling (Rf_error) are not safe to call from multiple threads.
// All parse operations must occur on the R main thread.

const char *record;
int _rxode2_reallyHasAfter = 0;
Expand All @@ -41,8 +45,20 @@ int lastStrLoc=0;
vLines _dupStrs;
char * rc_dup_str(const char *s, const char *e) {
lastStr=s;
int l = e ? e-s : (int)strlen(s);
//syntaxErrorExtra=min(l-1, 40);
int l;
if (e) {
ptrdiff_t diff = e - s;
if (diff < 0 || diff > (ptrdiff_t)INT_MAX) {
Rf_error(_("string segment too long in rc_dup_str"));
}
l = (int)diff;
} else {
size_t slen = strlen(s);
if (slen > (size_t)INT_MAX) {
Rf_error(_("string too long in rc_dup_str"));
}
l = (int)slen;
}
addLine(&_dupStrs, "%.*s", l, s);
return _dupStrs.line[_dupStrs.n-1];
}
8 changes: 7 additions & 1 deletion src/summaryData.c
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,13 @@ void trans_summaryData(const char* parse){
errP = curP;
eBufLast = 0;
gBufFree=0;
_pn= dparse(curP, gBuf, (int)strlen(gBuf));
{
size_t _gBuf_len = strlen(gBuf);
if (_gBuf_len > (size_t)INT_MAX) {
Rf_error(_("input too large to parse (exceeds INT_MAX bytes)"));
}
_pn= dparse(curP, gBuf, (int)_gBuf_len);
}
if (!_pn || curP->syntax_errors) {
} else {
wprint_parsetree_summaryData(parser_tables_summaryData , _pn, 0, wprint_node_summaryData, NULL);
Expand Down
19 changes: 0 additions & 19 deletions tests/testthat/_snaps/content.md

This file was deleted.

Loading
Loading