Mercurial > hg > octave-terminal
changeset 13754:e652ff4d1522
don't crash when concatenating structs with no fields
* oct-map.cc (octave_map::cat (int, octave_idx_type, const
octave_scalar_map*)): Quick return for N == 1.
(octave_map::cat (int, octave_idx_type, const octave_map*)):
Quick return for N == 1. Only call permute_to_correct_order if there
are fields. Use dim_vector::concat to compute result dimensions if
there are no fields.
New tests for concatentation of structs with no fields.
* pt-mat.cc (tm_const::init (const tree_matrix&)): Initialize all_1x1
to true if tree_matrix argument is not empty.
author | John W. Eaton <jwe@octave.org> |
---|---|
date | Wed, 26 Oct 2011 00:50:39 -0400 |
parents | ab4238b0b09b |
children | 8cd08124cb59 |
files | src/oct-map.cc src/pt-mat.cc |
diffstat | 2 files changed, 48 insertions(+), 13 deletions(-) [+] |
line wrap: on
line diff
--- a/src/oct-map.cc +++ b/src/oct-map.cc @@ -664,6 +664,7 @@ octave_map::cat (int dim, octave_idx_type n, const octave_scalar_map *map_list) { octave_map retval; + // Allow dim = -1, -2 for compatibility, though it makes no difference here. if (dim == -1 || dim == -2) dim = -dim - 1; @@ -671,7 +672,9 @@ (*current_liboctave_error_handler) ("cat: invalid dimension"); - if (n > 0) + if (n == 1) + retval = map_list[0]; + else if (n > 1) { octave_idx_type idx, nf = 0; for (idx = 0; idx < n; idx++) @@ -726,9 +729,20 @@ octave_map::cat (int dim, octave_idx_type n, const octave_map *map_list) { octave_map retval; - if (n > 0) + + // Allow dim = -1, -2 for compatibility, though it makes no difference here. + if (dim == -1 || dim == -2) + dim = -dim - 1; + else if (dim < 0) + (*current_liboctave_error_handler) + ("cat: invalid dimension"); + + if (n == 1) + retval = map_list[0]; + else if (n > 1) { octave_idx_type idx, nf = 0; + for (idx = 0; idx < n; idx++) { nf = map_list[idx].nfields (); @@ -752,20 +766,29 @@ do_cat (dim, n, map_list, retval); else { - // permute all structures to correct order. - OCTAVE_LOCAL_BUFFER (octave_map, new_map_list, n); + if (nf > 0) + { + // permute all structures to correct order. + OCTAVE_LOCAL_BUFFER (octave_map, new_map_list, n); - permute_to_correct_order (n, nf, idx, map_list, new_map_list); + permute_to_correct_order (n, nf, idx, map_list, new_map_list); - if (nf > 0) - do_cat (dim, n, new_map_list, retval); + do_cat (dim, n, new_map_list, retval); + } else { - // Use dummy arrays. FIXME: Need(?) a better solution. - OCTAVE_LOCAL_BUFFER (Array<char>, dummy, n); - for (octave_idx_type i = 0; i < n; i++) - dummy[i].clear (map_list[i].dimensions); - Array<char>::cat (dim, n, dummy); + dim_vector dv = map_list[0].dimensions; + + for (octave_idx_type i = 1; i < n; i++) + { + if (! dv.concat (map_list[i].dimensions, dim)) + { + error ("dimension mismatch in struct concatenation"); + return retval; + } + } + + retval.dimensions = dv; } } @@ -781,6 +804,18 @@ %! x(1, 1).d = 10; x(4, 6).a = "b"; x(2, 4).f = 27; %! y(1, 6).f = 11; y(1, 6).a = "c"; y(1, 6).d = 33; %! assert (fieldnames ([x; y]), {"d"; "a"; "f"}); + +%!test +%! s = struct (); +%! sr = [s,s]; +%! sc = [s;s]; +%! sm = [s,s;s,s]; +%! assert (nfields (sr), 0); +%! assert (nfields (sc), 0); +%! assert (nfields (sm), 0); +%! assert (size (sr), [1, 2]); +%! assert (size (sc), [2, 1]); +%! assert (size (sm), [2, 2]); */ octave_map