comparison libinterp/corefcn/cellfun.cc @ 31842:79abf4cdcd95

mat2cell: Next attempt to avoid heap buffer overflow (bug #63682). * libinterp/corefcn/cellfun.cc (do_mat2cell_nd): Use sufficiently large size for all temporary buffers. Use correct values for 2nd dimension if split-values for it are omitted in the input.
author Markus Mützel <markus.muetzel@gmx.de>
date Sun, 19 Feb 2023 17:19:24 +0100
parents 0e046fefbffa
children 0199ff6cc997
comparison
equal deleted inserted replaced
31841:0e046fefbffa 31842:79abf4cdcd95
2050 error_unless (nd >= 1); 2050 error_unless (nd >= 1);
2051 2051
2052 if (mat2cell_mismatch (a.dims (), d, nd)) 2052 if (mat2cell_mismatch (a.dims (), d, nd))
2053 return retval; 2053 return retval;
2054 2054
2055 bool is_1d = false;
2056 if (nd < 2)
2057 {
2058 // work with 2d matrix
2059 is_1d = true;
2060 nd = 2;
2061 }
2062
2063 // vector with number of splits in respective dimension
2055 dim_vector rdv = dim_vector::alloc (nd); 2064 dim_vector rdv = dim_vector::alloc (nd);
2056 OCTAVE_LOCAL_BUFFER (octave_idx_type, nidx, nd); 2065 OCTAVE_LOCAL_BUFFER (octave_idx_type, nidx, nd);
2057 octave_idx_type idxtot = 0; 2066 octave_idx_type idxtot = 0;
2058 for (int i = 0; i < nd; i++) 2067 for (int i = 0; i < (is_1d ? 1 : nd); i++)
2059 { 2068 {
2060 rdv(i) = nidx[i] = d[i].numel (); 2069 rdv(i) = nidx[i] = d[i].numel ();
2061 idxtot += nidx[i]; 2070 idxtot += nidx[i];
2062 } 2071 }
2063 2072
2064 if (nd == 1) 2073 if (is_1d)
2065 rdv(1) = 1; 2074 {
2075 // If input was 1d, don't split 2nd dimension.
2076 rdv(1) = nidx[1] = 1;
2077 idxtot++;
2078 }
2066 retval.clear (rdv); 2079 retval.clear (rdv);
2067 2080
2081 // buffer for "linearized" number of dimensions
2068 OCTAVE_LOCAL_BUFFER (idx_vector, xidx, idxtot); 2082 OCTAVE_LOCAL_BUFFER (idx_vector, xidx, idxtot);
2083 // buffer with size of respective dimensions after split
2069 OCTAVE_LOCAL_BUFFER (idx_vector *, idx, nd); 2084 OCTAVE_LOCAL_BUFFER (idx_vector *, idx, nd);
2070 2085
2071 idxtot = 0; 2086 idxtot = 0;
2072 for (int i = 0; i < nd; i++) 2087 for (int i = 0; i < (is_1d ? 1 : nd); i++)
2073 { 2088 {
2074 idx[i] = xidx + idxtot; 2089 idx[i] = xidx + idxtot;
2075 prepare_idx (idx[i], i, nd, d); 2090 prepare_idx (idx[i], i, nd, d);
2076 idxtot += nidx[i]; 2091 idxtot += nidx[i];
2077 } 2092 }
2078 2093
2079 OCTAVE_LOCAL_BUFFER_INIT (octave_idx_type, ridx, rdv.numel (), 0); 2094 if (is_1d)
2095 {
2096 // If input was 1d, take complete second dimension.
2097 idx[1] = xidx + idxtot;
2098 idx[1][0] = idx_vector::colon;
2099 }
2100
2101 OCTAVE_LOCAL_BUFFER_INIT (octave_idx_type, ridx, nd, 0);
2080 Array<idx_vector> ra_idx 2102 Array<idx_vector> ra_idx
2081 (dim_vector (1, std::max (nd, a.ndims ())), idx_vector::colon); 2103 (dim_vector (1, std::max (nd, a.ndims ())), idx_vector::colon);
2082 2104
2083 for (octave_idx_type j = 0; j < retval.numel (); j++) 2105 for (octave_idx_type j = 0; j < nd; j++)
2084 { 2106 {
2085 octave_quit (); 2107 octave_quit ();
2086 2108
2087 for (int i = 0; i < nd; i++) 2109 for (int i = 0; i < nd; i++)
2088 ra_idx.xelem (i) = idx[i][ridx[i]]; 2110 ra_idx.xelem (i) = idx[i][ridx[i]];