@@ -279,27 +279,32 @@ SEXP splitString(SEXP string, SEXP delims)
279279 int nc = (int ) strlen (in ), used = 0 ;
280280
281281 // Used for short strings, so OK to over-allocate wildly
282- SEXP out = PROTECT (allocVector (STRSXP , nc ));
283- const char * p ;
284- char tmp [nc ], * this = tmp ;
285- int nthis = 0 ;
286- for (p = in ; * p ; p ++ ) {
287- if (strchr (del , * p )) {
288- // put out current string (if any)
289- if (nthis )
290- SET_STRING_ELT (out , used ++ , mkCharLenCE (tmp , nthis , ienc ));
291- // put out delimiter
292- SET_STRING_ELT (out , used ++ , mkCharLen (p , 1 ));
293- // restart
294- this = tmp ; nthis = 0 ;
295- } else {
296- * this ++ = * p ;
297- nthis ++ ;
298- }
299- }
300- if (nthis ) SET_STRING_ELT (out , used ++ , mkCharLenCE (tmp , nthis , ienc ));
282+ SEXP out = PROTECT (allocVector (STRSXP , nc )), ans ;
301283
302- SEXP ans = lengthgets (out , used );
284+ // UBSAN objects if nc = 0, but we can skip that case.
285+ if (nc > 0 ) {
286+ char tmp [nc ], * this = tmp ;
287+ int nthis = 0 ;
288+ const char * p ;
289+ for (p = in ; * p ; p ++ ) {
290+ if (strchr (del , * p )) {
291+ // put out current string (if any)
292+ if (nthis )
293+ SET_STRING_ELT (out , used ++ , mkCharLenCE (tmp , nthis , ienc ));
294+ // put out delimiter
295+ SET_STRING_ELT (out , used ++ , mkCharLen (p , 1 ));
296+ // restart
297+ this = tmp ; nthis = 0 ;
298+ } else {
299+ * this ++ = * p ;
300+ nthis ++ ;
301+ }
302+ }
303+ if (nthis ) SET_STRING_ELT (out , used ++ , mkCharLenCE (tmp , nthis , ienc ));
304+
305+ ans = lengthgets (out , used );
306+ } else
307+ ans = out ;
303308 UNPROTECT (1 );
304309 return ans ;
305310}
0 commit comments