Skip to content

Commit 11498fd

Browse files
authored
Merge pull request #4324 from gaborbernat/master
R6: Fix null pointer crash in tokenDelete function
2 parents ead1d93 + 2bfc47b commit 11498fd

File tree

5 files changed

+29
-7
lines changed

5 files changed

+29
-7
lines changed
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
--sort=no
2+
--fields=+ilaKSe{extras}
3+
--extras=-p
4+
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
TestCase1 input.r /^TestCase1 <- R6::SomethingElse("TestCase1")$/;" globalVar language:R end:6
2+
TestCase2 input.r /^TestCase2 <- R6::$/;" globalVar language:R end:10
3+
TestCase3 input.r /^TestCase3 <- R6::R6Clas("TestCase3")$/;" globalVar language:R end:12
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# Test case for R6 parser null pointer regression
2+
# This triggers the error path in r6ReadRightSideSymbol that was causing
3+
# tokenDelete to be called with NULL pointers
4+
5+
# Case 1: R6:: followed by something other than R6Class
6+
TestCase1 <- R6::SomethingElse("TestCase1")
7+
8+
# Case 2: Incomplete R6 namespace reference
9+
TestCase2 <- R6::
10+
11+
# Case 3: R6 followed by :: but with syntax error
12+
TestCase3 <- R6::R6Clas("TestCase3")
13+

main/tokeninfo.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,8 @@ void flashTokenBacklog (struct tokenInfoClass *klass)
9191

9292
void tokenDelete (tokenInfo *token)
9393
{
94-
objPoolPut (token->klass->pool, token);
94+
if (token != NULL)
95+
objPoolPut (token->klass->pool, token);
9596
}
9697

9798

parsers/r-r6class.c

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -219,14 +219,14 @@ static int r6ReadRightSideSymbol (rSubparser *s,
219219
tokenInfo * token1 = NULL;
220220
if (strcmp (tokenString (token), "R6") == 0)
221221
{
222-
tokenInfo * token0 = rNewToken ();
222+
token0 = rNewToken ();
223223
tokenRead (token0);
224224
if (!tokenIsType (token0, R_SCOPE))
225225
goto reject;
226226
if (strcmp (tokenString (token0), "::"))
227227
goto reject;
228228

229-
tokenInfo * token1 = rNewToken ();
229+
token1 = rNewToken ();
230230
tokenRead (token1);
231231
if (!tokenIsType (token1, R_SYMBOL))
232232
goto reject;
@@ -252,11 +252,12 @@ static int r6ReadRightSideSymbol (rSubparser *s,
252252
}
253253
return CORK_NIL;
254254
reject:
255-
if (token1)
255+
/* For incomplete "R6::" cases, we don't want to unread the "::" token
256+
as the main R parser may not handle it well. */
257+
if (token1 && tokenIsType(token1, R_SYMBOL)) {
256258
tokenUnread (token1);
257-
if (token0)
258-
tokenUnread (token0);
259-
/* tokenDelete accepts NULL. */
259+
}
260+
/* Don't unread token0 (::) to prevent main parser confusion */
260261
tokenDelete (token1);
261262
tokenDelete (token0);
262263

0 commit comments

Comments
 (0)