comparison src/ov-class.cc @ 9148:69e6bbfef8c2

ov-class.cc: protect against possiblly invalid octave_value -> string conversions
author John W. Eaton <jwe@octave.org>
date Wed, 22 Apr 2009 14:41:27 -0400
parents 5579998f8acf
children d8f9588c6ba1
comparison
equal deleted inserted replaced
9147:5579998f8acf 9148:69e6bbfef8c2
91 91
92 if (! error_state) 92 if (! error_state)
93 load_path::add_to_parent_map (id, parent_list); 93 load_path::add_to_parent_map (id, parent_list);
94 } 94 }
95 95
96 octave_base_value *
97 octave_class::find_parent_class (const std::string& parent_class_name)
98 {
99 octave_base_value* retval = 0;
100
101 if (parent_class_name == class_name ())
102 retval = this;
103 else
104 {
105 for (std::list<std::string>::iterator pit = parent_list.begin ();
106 pit != parent_list.end ();
107 pit++)
108 {
109 Octave_map::const_iterator smap = map.seek (*pit);
110
111 const Cell& tmp = smap->second;
112
113 octave_value vtmp = tmp(0);
114
115 octave_base_value *obvp = vtmp.internal_rep ();
116
117 retval = obvp->find_parent_class (parent_class_name);
118
119 if (retval)
120 break;
121 }
122 }
123
124 return retval;
125 }
126
127 static std::string 96 static std::string
128 get_current_method_class (void) 97 get_current_method_class (void)
129 { 98 {
130 // FIXME -- is there a better way to do this? 99 // FIXME -- is there a better way to do this?
131 octave_function *fcn = octave_call_stack::current (); 100 octave_function *fcn = octave_call_stack::current ();
135 size_t ipos = my_dir.find_last_of ("@"); 104 size_t ipos = my_dir.find_last_of ("@");
136 105
137 assert (ipos != std::string::npos); 106 assert (ipos != std::string::npos);
138 107
139 return my_dir.substr (ipos+1); 108 return my_dir.substr (ipos+1);
140 }
141
142 Cell
143 octave_class::dotref (const octave_value_list& idx)
144 {
145 Cell retval;
146
147 assert (idx.length () == 1);
148
149 std::string method_class = get_current_method_class ();
150
151 // Find the class in which this method resides before attempting to access
152 // the requested field.
153
154 octave_base_value *obvp = find_parent_class (method_class);
155
156 Octave_map my_map;
157
158 my_map = obvp ? obvp->map_value () : map;
159
160 std::string nm = idx(0).string_value ();
161
162 Octave_map::const_iterator p = my_map.seek (nm);
163
164 if (p != my_map.end ())
165 retval = my_map.contents (p);
166 else
167 error ("class has no member `%s'", nm.c_str ());
168
169 return retval;
170 } 109 }
171 110
172 static void 111 static void
173 gripe_invalid_index (void) 112 gripe_invalid_index (void)
174 { 113 {
282 error ("invalid index for %s", who.c_str ()); 221 error ("invalid index for %s", who.c_str ());
283 222
284 return retval; 223 return retval;
285 } 224 }
286 225
226 Cell
227 octave_class::dotref (const octave_value_list& idx)
228 {
229 Cell retval;
230
231 assert (idx.length () == 1);
232
233 std::string method_class = get_current_method_class ();
234
235 // Find the class in which this method resides before attempting to access
236 // the requested field.
237
238 octave_base_value *obvp = find_parent_class (method_class);
239
240 Octave_map my_map;
241
242 my_map = obvp ? obvp->map_value () : map;
243
244 std::string nm = idx(0).string_value ();
245
246 if (! error_state)
247 {
248 Octave_map::const_iterator p = my_map.seek (nm);
249
250 if (p != my_map.end ())
251 retval = my_map.contents (p);
252 else
253 error ("class has no member `%s'", nm.c_str ());
254 }
255 else
256 gripe_invalid_index ();
257
258 return retval;
259 }
260
287 octave_value_list 261 octave_value_list
288 octave_class::subsref (const std::string& type, 262 octave_class::subsref (const std::string& type,
289 const std::list<octave_value_list>& idx, 263 const std::list<octave_value_list>& idx,
290 int nargout) 264 int nargout)
291 { 265 {
466 440
467 assert (key_idx.length () == 1); 441 assert (key_idx.length () == 1);
468 442
469 std::string key = key_idx(0).string_value (); 443 std::string key = key_idx(0).string_value ();
470 444
471 octave_value u;
472
473 if (! map.contains (key))
474 u = octave_value::empty_conv (type.substr (2), rhs);
475 else
476 {
477 Cell map_val = map.contents (key);
478
479 Cell map_elt = map_val.index (idx.front (), true);
480
481 u = numeric_conv (map_elt, type.substr (2));
482 }
483
484 if (! error_state) 445 if (! error_state)
485 { 446 {
486 std::list<octave_value_list> next_idx (idx); 447 octave_value u;
487 448
488 // We handled two index elements, so subsasgn to 449 if (! map.contains (key))
489 // needs to skip both of them. 450 u = octave_value::empty_conv (type.substr (2), rhs);
490 451 else
491 next_idx.erase (next_idx.begin ()); 452 {
492 next_idx.erase (next_idx.begin ()); 453 Cell map_val = map.contents (key);
493 454
494 u.make_unique (); 455 Cell map_elt = map_val.index (idx.front (), true);
495 456
496 t_rhs = u.subsasgn (type.substr (2), next_idx, rhs); 457 u = numeric_conv (map_elt, type.substr (2));
458 }
459
460 if (! error_state)
461 {
462 std::list<octave_value_list> next_idx (idx);
463
464 // We handled two index elements, so subsasgn to
465 // needs to skip both of them.
466
467 next_idx.erase (next_idx.begin ());
468 next_idx.erase (next_idx.begin ());
469
470 u.make_unique ();
471
472 t_rhs = u.subsasgn (type.substr (2), next_idx, rhs);
473 }
497 } 474 }
475 else
476 gripe_invalid_index_for_assignment ();
498 } 477 }
499 else 478 else
500 gripe_invalid_index_for_assignment (); 479 gripe_invalid_index_for_assignment ();
501 } 480 }
502 break; 481 break;
507 486
508 assert (key_idx.length () == 1); 487 assert (key_idx.length () == 1);
509 488
510 std::string key = key_idx(0).string_value (); 489 std::string key = key_idx(0).string_value ();
511 490
512 octave_value u;
513
514 if (! map.contains (key))
515 u = octave_value::empty_conv (type.substr (1), rhs);
516 else
517 {
518 Cell map_val = map.contents (key);
519
520 u = numeric_conv (map_val, type.substr (1));
521 }
522
523 if (! error_state) 491 if (! error_state)
524 { 492 {
525 std::list<octave_value_list> next_idx (idx); 493 octave_value u;
526 494
527 next_idx.erase (next_idx.begin ()); 495 if (! map.contains (key))
528 496 u = octave_value::empty_conv (type.substr (1), rhs);
529 u.make_unique (); 497 else
530 498 {
531 t_rhs = u.subsasgn (type.substr (1), next_idx, rhs); 499 Cell map_val = map.contents (key);
500
501 u = numeric_conv (map_val, type.substr (1));
502 }
503
504 if (! error_state)
505 {
506 std::list<octave_value_list> next_idx (idx);
507
508 next_idx.erase (next_idx.begin ());
509
510 u.make_unique ();
511
512 t_rhs = u.subsasgn (type.substr (1), next_idx, rhs);
513 }
532 } 514 }
515 else
516 gripe_invalid_index_for_assignment ();
533 } 517 }
534 break; 518 break;
535 519
536 case '{': 520 case '{':
537 gripe_invalid_index_type (type_name (), type[0]); 521 gripe_invalid_index_type (type_name (), type[0]);
614 } 598 }
615 break; 599 break;
616 600
617 case '.': 601 case '.':
618 { 602 {
619 octave_value_list key_idx = idx.front ();
620
621 assert (key_idx.length () == 1);
622
623 std::string key = key_idx(0).string_value ();
624
625 // Find the class in which this method resides before 603 // Find the class in which this method resides before
626 // attempting to access the requested field. 604 // attempting to access the requested field.
627 605
628 std::string method_class = get_current_method_class (); 606 std::string method_class = get_current_method_class ();
629 607
630 octave_base_value *obvp = find_parent_class (method_class); 608 octave_base_value *obvp = find_parent_class (method_class);
631 609
632 if (obvp) 610 if (obvp)
633 { 611 {
634 obvp->assign (key, t_rhs); 612 octave_value_list key_idx = idx.front ();
613
614 assert (key_idx.length () == 1);
615
616 std::string key = key_idx(0).string_value ();
635 617
636 if (! error_state) 618 if (! error_state)
637 { 619 {
638 count++; 620 obvp->assign (key, t_rhs);
639 retval = octave_value (this); 621
622 if (! error_state)
623 {
624 count++;
625 retval = octave_value (this);
626 }
627 else
628 gripe_failed_assignment ();
640 } 629 }
641 else 630 else
642 gripe_failed_assignment (); 631 gripe_failed_assignment ();
643 } 632 }
644 else 633 else
716 string_vector 705 string_vector
717 octave_class::map_keys (void) const 706 octave_class::map_keys (void) const
718 { 707 {
719 string_vector retval; 708 string_vector retval;
720 gripe_wrong_type_arg ("octave_class::map_keys()", type_name ()); 709 gripe_wrong_type_arg ("octave_class::map_keys()", type_name ());
710 return retval;
711 }
712
713 octave_base_value *
714 octave_class::find_parent_class (const std::string& parent_class_name)
715 {
716 octave_base_value* retval = 0;
717
718 if (parent_class_name == class_name ())
719 retval = this;
720 else
721 {
722 for (std::list<std::string>::iterator pit = parent_list.begin ();
723 pit != parent_list.end ();
724 pit++)
725 {
726 Octave_map::const_iterator smap = map.seek (*pit);
727
728 const Cell& tmp = smap->second;
729
730 octave_value vtmp = tmp(0);
731
732 octave_base_value *obvp = vtmp.internal_rep ();
733
734 retval = obvp->find_parent_class (parent_class_name);
735
736 if (retval)
737 break;
738 }
739 }
740
721 return retval; 741 return retval;
722 } 742 }
723 743
724 void 744 void
725 octave_class::print (std::ostream& os, bool) const 745 octave_class::print (std::ostream& os, bool) const