Mercurial > octave-nkf
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 |