Mercurial > octave
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]]; |