diff --git a/src/assign.c b/src/assign.c index 29f5dff4c..5901d5a15 100644 --- a/src/assign.c +++ b/src/assign.c @@ -52,7 +52,7 @@ void setselfref(SEXP x) { */ static int _selfrefok(SEXP x, Rboolean checkNames, Rboolean verbose) { - SEXP v, p, tag, prot, names; + SEXP v, p, tag, prot; v = getAttrib(x, SelfRefSymbol); if (v==R_NilValue || TYPEOF(v)!=EXTPTRSXP) { // .internal.selfref missing is expected and normal for i) a pre v1.7.8 data.table loaded @@ -70,11 +70,11 @@ static int _selfrefok(SEXP x, Rboolean checkNames, Rboolean verbose) { if (!isNull(p)) internal_error(__func__, ".internal.selfref ptr is neither NULL nor R_NilValue"); // # nocov tag = R_ExternalPtrTag(v); if (!(isNull(tag) || isString(tag))) internal_error(__func__, ".internal.selfref tag is neither NULL nor a character vector"); // # nocov - names = getAttrib(x, R_NamesSymbol); prot = R_ExternalPtrProtected(v); if (TYPEOF(prot) != EXTPTRSXP) // Very rare. Was error(_(".internal.selfref prot is not itself an extptr")). return 0; // # nocov ; see http://stackoverflow.com/questions/15342227/getting-a-random-internal-selfref-error-in-data-table-for-r - return checkNames ? names==tag : x==R_ExternalPtrAddr(prot); + if (!checkNames) return x == R_ExternalPtrAddr(prot); + return getAttrib(x, R_NamesSymbol) == tag; } static Rboolean selfrefok(SEXP x, Rboolean verbose) { // for readability diff --git a/src/mergelist.c b/src/mergelist.c index 90854ae82..2ed395045 100644 --- a/src/mergelist.c +++ b/src/mergelist.c @@ -82,9 +82,10 @@ SEXP cbindlist(SEXP x, SEXP copyArg) { SET_VECTOR_ELT(ans, ians, thisxcol); SET_STRING_ELT(names, ians, STRING_ELT(thisnames, j)); } - mergeIndexAttrib(index, getAttrib(thisx, sym_index)); - if (isNull(key)) // first key is retained - key = getAttrib(thisx, sym_sorted); + mergeIndexAttrib(index, PROTECT(getAttrib(thisx, sym_index))); protecti++; + if (isNull(key)) { // first key is retained + key = PROTECT(getAttrib(thisx, sym_sorted)); protecti++; + } UNPROTECT(protecti); // thisnames, thisxcol } if (!ANY_ATTRIB(index)) diff --git a/src/rbindlist.c b/src/rbindlist.c index a752be6d3..a047b1d49 100644 --- a/src/rbindlist.c +++ b/src/rbindlist.c @@ -277,7 +277,9 @@ SEXP rbindlist(SEXP l, SEXP usenamesArg, SEXP fillArg, SEXP idcolArg, SEXP ignor int maxType=LGLSXP; // initialize with LGLSXP for test 2002.3 which has col x NULL in both lists to be filled with NA for #1871 bool factor=false, orderedFactor=false; // ordered factor is class c("ordered","factor"). isFactor() is true when isOrdered() is true. int longestLen=-1, longestW=-1, longestI=-1; // just for ordered factor; longestLen must be initialized as -1 so that rbind zero-length ordered factor could work #4795 + PROTECT_INDEX ILongestLevels; SEXP longestLevels=R_NilValue; // just for ordered factor + PROTECT_WITH_INDEX(longestLevels, &ILongestLevels); nprotect++; bool int64=false, date=false, posixct=false, itime=false, asis=false; const char *foundName=NULL; bool anyNotStringOrFactor=false; @@ -303,7 +305,7 @@ SEXP rbindlist(SEXP l, SEXP usenamesArg, SEXP fillArg, SEXP idcolArg, SEXP ignor if (isOrdered(thisCol)) { orderedFactor = true; int thisLen = length(getAttrib(thisCol, R_LevelsSymbol)); - if (thisLen>longestLen) { longestLen=thisLen; longestLevels=getAttrib(thisCol, R_LevelsSymbol); /*for warnings later ...*/longestW=w; longestI=i; } + if (thisLen > longestLen) { longestLen=thisLen; REPROTECT(longestLevels=getAttrib(thisCol, R_LevelsSymbol), ILongestLevels); /*for warnings later ...*/longestW=w; longestI=i; } } } else if (!isString(thisCol)) anyNotStringOrFactor=true; // even for length 0 columns for consistency; test 2113.3 if (INHERITS(thisCol, char_integer64)) { @@ -562,6 +564,6 @@ SEXP rbindlist(SEXP l, SEXP usenamesArg, SEXP fillArg, SEXP idcolArg, SEXP ignor } } } - UNPROTECT(nprotect); // ans, ansNames, coercedForFactor? + UNPROTECT(nprotect); // ans, ansNames, longestLevels? coercedForFactor? return(ans); }