"Fossies" - the Fresh Open Source Software Archive 
Member "gnash-0.8.10/libcore/abc/AbcBlock.cpp" (19 Jan 2012, 41350 Bytes) of package /linux/www/old/gnash-0.8.10.tar.gz:
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style:
standard) with prefixed line numbers and
code folding option.
Alternatively you can here
view or
download the uninterpreted source code file.
1 //
2 // Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012
3 // Free Software Foundation, Inc.
4 //
5 // This program is free software; you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation; either version 3 of the License, or
8 // (at your option) any later version.
9 //
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
14 //
15 // You should have received a copy of the GNU General Public License
16 // along with this program; if not, write to the Free Software
17 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18
19 // The AS3 abc block format reader.
20 //
21
22 #include "gnashconfig.h"
23 #include "AbcBlock.h"
24 #include "SWFStream.h" // for use
25 #include "VM.h"
26 #include "log.h"
27 #include "ClassHierarchy.h"
28 #include "Class.h"
29 #include "namedStrings.h"
30 #include "CodeStream.h"
31 #include "action_buffer.h"
32 #include "Machine.h"
33 #include "Global_as.h"
34
35 #include <boost/bind.hpp>
36
37 namespace gnash {
38
39 namespace abc {
40
41 bool
42 Trait::finalize(AbcBlock *block, abc::Class* script, bool do_static)
43 {
44 log_abc("Finalize class %s (%s), trait kind: %s",
45 block->_stringTable->value(script->getName()), script, _kind);
46
47 switch (_kind)
48 {
49 case KIND_SLOT:
50 case KIND_CONST:
51 {
52 // Validate the type.
53 abc::Class* type;
54 if (_typeIndex) {
55 log_abc("Trait type: %s",
56 block->_stringPool[
57 block->_multinamePool[_typeIndex].getABCName()]);
58 type = block->locateClass(block->_multinamePool[_typeIndex]);
59 }
60 else {
61 type = block->mTheObject;
62 }
63
64 if (!type) {
65 log_error(_("ABC: Finalizing trait yielded bad type for slot."));
66 return false;
67 }
68
69 // The name has been validated in read.
70 // TODO: Find a better way to initialize trait values.
71 if (!_hasValue) {
72 as_object* null = 0;
73 _value = null;
74 }
75
76 log_abc("Adding property=%s with value=%s slot=%u",
77 block->_stringPool[_name], _value, _slotID);
78
79 script->addValue(_globalName, _namespace, _slotID, type,
80 _value, _kind == KIND_CONST, do_static);
81 break;
82 }
83
84 case KIND_METHOD:
85 script->addMethod(_globalName, _namespace, _method, false);
86 break;
87
88 case KIND_GETTER:
89 script->addGetter(_name, _namespace, _method, do_static);
90 break;
91
92 case KIND_SETTER:
93 script->addSetter(_name, _namespace, _method, do_static);
94 break;
95
96 case KIND_CLASS:
97 log_abc("Adding class %s, value %s, slot=%u",
98 block->_stringPool[_name], _value, _slotID);
99 script->addMemberScript(_globalName, _namespace, _slotID,
100 block->_classes[_classInfoIndex], do_static);
101 break;
102
103 case KIND_FUNCTION:
104 script->addSlotFunction(_name, _namespace, _slotID, _method,
105 do_static);
106 break;
107
108 default:
109 return false;
110 }
111 return true;
112 }
113
114 bool
115 Trait::finalize_mbody(AbcBlock *block, Method *pMethod)
116 {
117 log_abc("Finalizing method trait: kind %s", _kind);
118 switch (_kind)
119 {
120 case KIND_SLOT:
121 case KIND_CONST:
122 {
123 // Validate the type.
124 abc::Class *type;
125 if (_typeIndex) {
126 type = block->locateClass(block->_multinamePool[_typeIndex]);
127 }
128 else {
129 type = block->mTheObject;
130 }
131
132 if (!type) {
133 log_error(_("ABC: Finalizing trait yielded bad type for slot."));
134 return false;
135 }
136
137 // The name has been validated in read.
138 // TODO: Find a better way to initialize trait values.
139 if (!_hasValue) {
140 _value = as_value((as_object*)0); // NULL value, right ?
141 }
142 log_abc("Adding property=%s with value=%s slot=%u",
143 block->_stringPool[_name], _value.toDebugString(), _slotID);
144 pMethod->addValue(_globalName, _namespace, _slotID, type,
145 _value, _kind == KIND_CONST);
146 break;
147 }
148 case KIND_METHOD:
149 {
150 pMethod->addMethod(_name, _namespace, _method);
151 break;
152 }
153 case KIND_GETTER:
154 {
155 pMethod->addGetter(_name, _namespace, _method);
156 break;
157 }
158 case KIND_SETTER:
159 {
160 pMethod->addSetter(_name, _namespace, _method);
161 break;
162 }
163 case KIND_CLASS:
164 {
165 pMethod->addMemberScript(_name, _namespace, _slotID,
166 block->_classes[_classInfoIndex]);
167 break;
168 }
169 case KIND_FUNCTION:
170 {
171 pMethod->addSlotFunction(_name, _namespace, _slotID, _method);
172 break;
173 }
174 default:
175 // Not here -- validated already in read.
176 return false;
177 }
178 return true;
179 }
180
181 /// Read an AS3 'trait'
182 bool
183 Trait::read(SWFStream* in, AbcBlock *block)
184 {
185 boost::uint32_t name = in->read_V32();
186 if (name >= block->_multinamePool.size())
187 {
188 log_error(_("ABC: Bad name for trait."));
189 return false;
190 }
191 if (!block->_multinamePool[name].isQName())
192 {
193 log_error(_("ABC: Trait name must be fully qualified."));
194 return false;
195 }
196 MultiName multiname = block->_multinamePool[name];
197 _name = block->_multinamePool[name].getABCName();
198 _globalName = block->_multinamePool[name].getGlobalName();
199 _namespace = block->_multinamePool[name].getNamespace();
200
201 boost::uint8_t kind = in->read_u8();
202 _kind = static_cast<Kind>(kind & 0x0F);
203
204 log_abc("Trait name: %s, Trait kind: %s",
205 block->_stringPool[multiname.getABCName()], _kind);
206
207 switch (_kind)
208 {
209 case KIND_SLOT:
210 case KIND_CONST:
211 {
212 _slotID = in->read_V32();
213 _typeIndex = in->read_V32();
214 boost::uint32_t vindex = in->read_V32();
215 log_abc("Slot ID=%u Type=%s Pool index=%u", _slotID,
216 block->_stringPool[
217 block->_multinamePool[_typeIndex].getABCName()], vindex);
218
219 if (vindex) {
220 const AbcBlock::PoolConstant c =
221 static_cast<AbcBlock::PoolConstant>(in->read_u8());
222
223 if (!block->pool_value(vindex, c, _value))
224 return false; // Message done by pool_value
225 _hasValue = true;
226 }
227 else _hasValue = false;
228 break;
229 }
230 case KIND_METHOD:
231 case KIND_GETTER:
232 case KIND_SETTER:
233 {
234 // Ignore the 'disp_id'
235 in->skip_V32();
236
237 boost::uint32_t offset = in->read_V32();
238 log_abc("Method index=%u", offset);
239 if (offset >= block->_methods.size()) {
240 log_error(_("Bad method id in trait."));
241 return false;
242 }
243 _method = block->_methods[offset];
244 break;
245 }
246 case KIND_CLASS:
247 {
248 _slotID = in->read_V32();
249 _classInfoIndex = in->read_V32();
250 log_abc("Slot id: %u Class index: %u Class Name: %s", _slotID,
251 _classInfoIndex,
252 block->_stringTable->value(
253 block->_classes[_classInfoIndex]->getName()));
254
255 if (_classInfoIndex >= block->_classes.size()) {
256 log_error(_("Bad Class id in trait."));
257 return false;
258 }
259 break;
260 }
261 case KIND_FUNCTION:
262 {
263 _slotID = in->read_V32();
264 boost::uint32_t offset = in->read_V32();
265 if (offset >= block->_methods.size()) {
266 log_error(_("Bad method id in trait."));
267 return false;
268 }
269 _method = block->_methods[offset];
270 break;
271 }
272 default:
273 {
274 log_error(_("ABC: Unknown type of trait."));
275 }
276 }
277
278 // Ignore the metadata, but it must be read to know how to ignore it.
279 if ((kind >> 4) & 0x04) {
280 boost::uint32_t mcount = in->read_V32();
281 for (size_t i = 0; i < mcount; ++i) {
282 in->skip_V32();
283 }
284 }
285 return true;
286 }
287
288 std::ostream&
289 operator<<(std::ostream& o, const Trait::Kind k)
290 {
291 switch (k) {
292 case abc::Trait::KIND_SLOT:
293 return o << "slot";
294 case abc::Trait::KIND_CONST:
295 return o << "const";
296 case abc::Trait::KIND_METHOD:
297 return o << "method";
298 case abc::Trait::KIND_GETTER:
299 return o << "getter";
300 case abc::Trait::KIND_SETTER:
301 return o << "setter";
302 case abc::Trait::KIND_CLASS:
303 return o << "class";
304 case abc::Trait::KIND_FUNCTION:
305 return o << "function";
306 default:
307 return o << "Unknown kind " << static_cast<int>(k);
308 }
309 }
310
311 AbcBlock::AbcBlock()
312 :
313 _stringTable(&VM::get().getStringTable())
314 {
315 mCH = &VM::get().getMachine()->global()->classHierarchy();
316 // TODO: Make this the real 'Object' prototype.
317 mCH->getGlobalNs()->stubPrototype(*mCH, NSV::CLASS_OBJECT);
318 mTheObject = mCH->getGlobalNs()->getScript(NSV::CLASS_OBJECT);
319 }
320
321 void
322 AbcBlock::prepare(Machine* mach)
323 {
324
325 std::for_each(_classes.begin(), _classes.end(),
326 std::mem_fun(&abc::Class::initPrototype));
327 // The last (entry) script has Global as its prototype.
328 // This can be deduced because the global classes are initialized with a
329 // slot on script 0 (entry script). OpNewClass then attempts to set the
330 // corresponding slot once the class has been constructed. At this point,
331 // global should verifiably be on the stack, so the slots are expected
332 // to be set on the global object.
333 // It seems likely, though testing it is not straightforward, that all
334 // scripts have Global as a target object (prototype), so for now we
335 // will do that.
336 std::for_each(_scripts.begin(), _scripts.end(),
337 boost::bind(&abc::Class::setPrototype, _1, mach->global()));
338
339 std::for_each(_methods.begin(), _methods.end(),
340 boost::bind(&Method::initPrototype, _1, mach));
341
342 // TODO: Remove this, initialize traits only when needed; possibly
343 // consruct them on parsing without the need for a finalize method.
344 std::for_each(_methods.begin(), _methods.end(),
345 boost::bind(&abc::Method::initTraits, _1, *this));
346 std::for_each(_classes.begin(), _classes.end(),
347 boost::bind(&abc::Class::initTraits, _1, *this));
348 std::for_each(_scripts.begin(), _scripts.end(),
349 boost::bind(&abc::Class::initTraits, _1, *this));
350
351 }
352
353 void
354 AbcBlock::check_multiname_name(boost::uint32_t name)
355 {
356
357 if (name >= _stringPool.size()) {
358 throw ParserException("ABC: Out of bounds string for Multiname.");
359 }
360 }
361
362 void
363 AbcBlock::check_multiname_namespace(boost::uint32_t ns)
364 {
365 if (ns >= _namespacePool.size()) {
366 throw ParserException("ABC: Out of bounds namespace for Multiname.");
367 }
368 }
369
370 void
371 AbcBlock::check_multiname_namespaceset(boost::uint32_t nsset)
372 {
373 if (!nsset)
374 {
375 throw ParserException("ABC: 0 selection for namespace set is invalid.");
376 }
377 if (nsset >= _namespaceSetPool.size())
378 {
379 throw ParserException("ABC: Out of bounds namespace set for Multiname.");
380 }
381 }
382
383 void
384 AbcBlock::setMultinameNames(MultiName *n, abc::URI ABCName)
385 {
386
387 n->setABCName(ABCName);
388 std::string name = _stringPool[ABCName];
389 string_table::key global_key = _stringTable->find(name, true);
390 log_abc("Global key %u", global_key);
391 n->setGlobalName(global_key);
392 log_abc("Multiname: %s ABCName set to %u, global name set to %u",
393 name, n->getABCName(), n->getGlobalName());
394 }
395
396 void
397 AbcBlock::setNamespaceURI(Namespace *ns, abc::URI ABCName)
398 {
399 std::string name = _stringPool[ABCName];
400 string_table::key global_key = _stringTable->find(name);
401 ns->setURI(global_key);
402 log_abc("Namespace: %s AbcURI=%u URI=%u.", name, ABCName, global_key);
403 }
404
405 abc::Class*
406 AbcBlock::locateClass(const std::string& className)
407 {
408
409 const std::string::size_type pos = className.rfind(".");
410
411 MultiName a;
412
413 const std::string& nsstr = (pos != std::string::npos) ?
414 className.substr(0, pos) : "";
415
416 const std::string& clstr = (pos != std::string::npos) ?
417 className.substr(pos + 1) : className;
418
419 a.setGlobalName(_stringTable->find(clstr));
420
421 for (std::vector<Namespace*>::iterator i = _namespacePool.begin();
422 i != _namespacePool.end(); ++i) {
423
424 const size_t key = (*i)->getURI();
425
426 if (key == _stringTable->find(nsstr)) {
427 a.setNamespace(*i);
428 break;
429 }
430 }
431
432 return locateClass(a);
433
434 }
435
436 abc::Class*
437 AbcBlock::locateClass(MultiName& m)
438 {
439 abc::Class* found = 0;
440
441 if (m.getNamespace())
442 {
443 found = m.getNamespace()->getScript(m.getGlobalName());
444 if (found) return found;
445 }
446 if (m.namespaceSet() && !m.namespaceSet()->empty())
447 {
448 std::vector<Namespace*>::const_iterator i;
449 for (i = m.namespaceSet()->begin(); i != m.namespaceSet()->end(); ++i) {
450
451 found = (*i)->getScript(m.getGlobalName());
452 if (found) return found;
453 }
454 }
455
456 log_abc("Could not locate class in ABC block resources!");
457
458 return 0;
459
460 }
461
462 /// Read the ActionBlock version number.
463 bool
464 AbcBlock::read_version()
465 {
466 // Minor version, major version.
467 mVersion = (_stream->read_u16()) | (_stream->read_u16() << 16);
468 log_debug(_("Abc Version: %d.%d"), (mVersion & 0xFFFF0000) >> 16,
469 (mVersion & 0x0000FFFF));
470 return true;
471 }
472
473 /// Read the pool of integer constants.
474 bool
475 AbcBlock::read_integer_constants()
476 {
477 // count overestimates by 1.
478 boost::uint32_t count = _stream->read_V32();
479 _integerPool.resize(count);
480 if (count)
481 _integerPool[0] = 0;
482 for (unsigned int i = 1; i < count; ++i)
483 {
484 _integerPool[i] = static_cast<boost::int32_t> (_stream->read_V32());
485 }
486 return true;
487 }
488
489 /// Read the pool of unsigned integer constants.
490 bool
491 AbcBlock::read_unsigned_integer_constants()
492 {
493 // count overestimates by 1.
494 boost::uint32_t count = _stream->read_V32();
495 _uIntegerPool.resize(count);
496 if (count)
497 _uIntegerPool[0] = 0;
498 for (unsigned int i = 1; i < count; ++i)
499 {
500 _uIntegerPool[i] = _stream->read_V32();
501 }
502 return true;
503 }
504
505 /// Read the pool of 64-bit double constants.
506 bool
507 AbcBlock::read_double_constants()
508 {
509 boost::uint32_t count = _stream->read_V32();
510 _doublePool.resize(count);
511 if (count) _doublePool[0] = 0.0;
512
513 for (size_t i = 1; i < count; ++i)
514 {
515 _doublePool[i] = _stream->read_d64();
516 log_abc("Double %u=%lf", i, _doublePool[i]);
517 }
518 return true;
519 }
520
521 /// Read the pool of string constants.
522 bool
523 AbcBlock::read_string_constants()
524 {
525 log_abc("Begin reading string constants.");
526 boost::uint32_t count = _stream->read_V32();
527 log_abc("There are %u string constants.", count);
528 _stringPool.resize(count);
529
530 if (count) {
531 _stringPool[0] = "";
532 }
533
534 for (size_t i = 1; i < count; ++i) {
535 boost::uint32_t length = _stream->read_V32();
536 _stream->read_string_with_length(length, _stringPool[i]);
537 log_abc("Adding string constant to string pool: index=%u %s",
538 i, _stringPool[i]);
539 }
540 return true;
541 }
542
543 /// Read the pool of namespaces
544 /// Any two namespaces with the same uri here are the same namespace,
545 /// excepting private namespaces.
546 bool
547 AbcBlock::read_namespaces()
548 {
549 log_abc("Begin reading namespaces.");
550 boost::uint32_t count = _stream->read_V32();
551 log_abc("There are %u namespaces.", count);
552 _namespacePool.resize(count);
553 if (count) {
554 _namespacePool[0] = mCH->getGlobalNs();
555 }
556
557 for (size_t i = 1; i < count; ++i)
558 {
559 NamespaceConstant kind =
560 static_cast<NamespaceConstant>(_stream->read_u8());
561
562 boost::uint32_t nameIndex = _stream->read_V32();
563 log_abc("Namespace %u: %s, index %u, name %s", i, kind,
564 nameIndex, _stringPool[nameIndex]);
565
566 if (nameIndex >= _stringPool.size()) {
567 log_error(_("ABC: Bad string given for namespace."));
568 return false;
569 }
570
571 if (kind == PRIVATE_NS)
572 {
573 _namespacePool[i] = mCH->anonNamespace(nameIndex);
574 _namespacePool[i]->setPrivate();
575 }
576 else
577 {
578 string_table::key gn = _stringTable->find(_stringPool[nameIndex]);
579 Namespace *n = mCH->findNamespace(gn);
580 if (!n) n = mCH->addNamespace(gn);
581 _namespacePool[i] = n;
582 }
583 if (kind == PROTECTED_NS) _namespacePool[i]->setProtected();
584 if (kind == PACKAGE_NS) _namespacePool[i]->setPackage();
585 setNamespaceURI(_namespacePool[i], nameIndex);
586 }
587 return true;
588 }
589
590 /// Read the set of sets of namespaces.
591 bool
592 AbcBlock::read_namespace_sets()
593 {
594 boost::uint32_t count = _stream->read_V32();
595 _namespaceSetPool.resize(count);
596 if (count)
597 {
598 _namespaceSetPool[0].resize(0);
599 }
600 for (unsigned int i = 1; i < count; ++i)
601 {
602 boost::uint32_t icount = _stream->read_V32();
603 _namespaceSetPool[i].resize(icount);
604 for (unsigned int j = 0; j < icount; ++j)
605 {
606 boost::uint32_t selection = _stream->read_V32();
607 if (!selection || selection >= _namespacePool.size())
608 {
609 log_error(_("ABC: Bad namespace for namespace set."));
610 return false;
611 }
612 _namespaceSetPool[i][j] = _namespacePool[selection];
613 }
614 }
615 return true;
616 }
617
618 /// Read the multinames.
619 bool
620 AbcBlock::read_multinames()
621 {
622 boost::uint32_t count = _stream->read_V32();
623 log_abc("There are %u multinames.", count);
624 _multinamePool.resize(count);
625 if (count)
626 {
627 // _multinamePool[0].setABCName(0);
628 setMultinameNames(&_multinamePool[0], 0);
629 _multinamePool[0].setNamespace(mCH->getGlobalNs());
630 }
631 for (unsigned int i = 1; i < count; ++i)
632 {
633 MultiName::Kind kind = static_cast<MultiName::Kind>(_stream->read_u8());
634 boost::uint32_t ns = 0;
635 boost::uint32_t name = 0;
636 boost::uint32_t nsset = 0;
637
638 log_abc("Multiname %u has kind %s", i, static_cast<int>(kind));
639
640 // Read, but don't upper validate until after the switch.
641 switch (kind)
642 {
643 case MultiName::KIND_Qname:
644 case MultiName::KIND_QnameA:
645 ns = _stream->read_V32();
646 check_multiname_namespace(ns);
647 name = _stream->read_V32();
648 check_multiname_name(name);
649 log_abc("\tnamespace_index=%u name_index=%u name=%s",
650 ns, name, _stringPool[name]);
651 break;
652
653 case MultiName::KIND_RTQname:
654 case MultiName::KIND_RTQnameA:
655 name = _stream->read_V32();
656 check_multiname_name(name);
657 break;
658
659 case MultiName::KIND_RTQnameL:
660 case MultiName::KIND_RTQnameLA:
661 break;
662
663 case MultiName::KIND_Multiname:
664 case MultiName::KIND_MultinameA:
665 name = _stream->read_V32();
666 check_multiname_name(name);
667 nsset = _stream->read_V32();
668 check_multiname_namespaceset(nsset);
669 break;
670
671 case MultiName::KIND_MultinameL:
672 case MultiName::KIND_MultinameLA:
673 nsset = _stream->read_V32();
674 check_multiname_namespaceset(nsset);
675 break;
676
677 default:
678 // Unknown type.
679 log_error(_("Action Block: Unknown multiname type (%d)."),
680 kind);
681 return false;
682 }
683
684 _multinamePool[i].setFlags(kind);
685 setMultinameNames(&_multinamePool[i], name);
686 log_abc("Done setting multinames: abc=%u global=%u",
687 _multinamePool[i].getABCName(),
688 _multinamePool[i].getGlobalName());
689
690 _multinamePool[i].setNamespace(_namespacePool[ns]);
691
692 if (nsset) {
693 _multinamePool[i].namespaceSet(&_namespaceSetPool[nsset]);
694 }
695 } // End of main loop.
696 return true;
697 }
698
699 bool
700 AbcBlock::pool_value(boost::uint32_t index, PoolConstant type, as_value &v)
701 {
702 if (!index)
703 return true;
704
705 log_abc("Pool value: index is %u type is 0x%X", index, type | 0x0);
706 switch (type)
707 {
708 case POOL_STRING:
709 {
710 if (index >= _stringPool.size())
711 {
712 log_error(_("Action Block: Bad index in optional argument."));
713 return false;
714 }
715 v.set_string(_stringPool[index]);
716 break;
717 }
718 case POOL_INTEGER:
719 {
720 if (index >= _integerPool.size())
721 {
722 log_error(_("Action Block: Bad index in optional argument."));
723 return false;
724 }
725 v.set_double(_integerPool[index]);
726 break;
727 }
728 case POOL_UINTEGER:
729 {
730 if (index >= _uIntegerPool.size())
731 {
732 log_error(_("Action Block: Bad index in optional argument."));
733 return false;
734 }
735 v.set_double(_uIntegerPool[index]);
736 break;
737 }
738 case POOL_DOUBLE:
739 {
740 if (index >= _doublePool.size())
741 {
742 log_error(_("Action Block: Bad index in optional argument."));
743 return false;
744 }
745 v.set_double(static_cast<double>(_doublePool[index]));
746 break;
747 }
748 case POOL_NAMESPACE: // Namespace
749 {
750 if (index >= _namespacePool.size())
751 {
752 log_error(_("ABC: Bad index in optional argument, namespaces."));
753 return false;
754 }
755 break;
756 }
757 case POOL_FALSE: // False value
758 {
759 v.set_bool(false);
760 break;
761 }
762 case POOL_TRUE: // True value
763 {
764 v.set_bool(true);
765 break;
766 }
767 case POOL_NULL: // NULL value
768 {
769 v.set_null();
770 break;
771 }
772 default: // All others are bogus.
773 {
774 log_error(_("ABC: Bad default value type (%X), but continuing."), type);
775 return true;
776 break;
777 }
778 } // end of switch
779 return true;
780 }
781
782 /// Read the method infos.
783 bool
784 AbcBlock::read_method_infos()
785 {
786 log_abc("Begin read_method_infos.");
787
788 boost::uint32_t count = _stream->read_V32();
789 log_abc("Method count: %u", count);
790
791 _methods.resize(count);
792 for (unsigned int i = 0; i < count; ++i)
793 {
794 log_abc(" Reading method %u", i);
795 Method *pMethod = mCH->newMethod();
796 pMethod->setMethodID(i);
797 _methods[i] = pMethod;
798 boost::uint32_t param_count = _stream->read_V32();
799 boost::uint32_t return_type = _stream->read_V32();
800
801 const std::string& rt = return_type ?
802 _stringPool[_multinamePool[return_type].getABCName()] :
803 "*";
804
805 log_abc(" Param count: %u, return type: %s", param_count,
806 rt, return_type);
807
808 pMethod->setMinArgumentCount(param_count);
809 pMethod->setMaxArgumentCount(param_count);
810
811 if (return_type >= _multinamePool.size()) {
812 log_error(_("ABC: Bad return type for method info."));
813 return false;
814 }
815
816 if (!return_type) {
817 pMethod->setReturnType(0);
818 }
819 else {
820 // TODO: this can be 'void', which clearly isn't a class, so this
821 // seems bogus. As setReturnType is a no-op, we should log it
822 // and ignore it.
823 abc::Class* rtScript = locateClass(_multinamePool[return_type]);
824 if (!rtScript) {
825 log_abc(_("ABC: Unknown return type."));
826 }
827
828 pMethod->setReturnType(rtScript);
829 }
830 for (size_t j = 0; j < param_count; ++j) {
831 log_abc(" Reading parameter %u", j);
832 // The parameter type.
833 boost::uint32_t ptype = _stream->read_V32();
834
835 const std::string& pt = return_type ?
836 _stringPool[_multinamePool[ptype].getABCName()] :
837 "*";
838
839 log_abc(" Parameter type(index): %s(%u)", pt, ptype);
840
841 if (ptype >= _multinamePool.size()) {
842 log_error(_("ABC: Bad parameter type in method."));
843 return false;
844 }
845
846 // A value of 0 is legitimate, meaning 'any (*)'.
847 if (ptype) {
848 abc::Class* param_type = locateClass(_multinamePool[ptype]);
849
850 if (!param_type) {
851 log_abc((_("ABC: Unknown parameter type.")));
852 }
853
854 // This currently also pushes 0, meaning 'any'; perhaps it
855 // should throw a VerifyError if the class is not known.
856 pMethod->pushArgument(param_type);
857 }
858 else {
859 pMethod->pushArgument(0);
860 }
861 }
862
863 boost::uint32_t method_name = _stream->read_V32();
864 log_abc( "Method name=%s %d", _stringPool[method_name], method_name);
865 boost::uint8_t flags = _stream->read_u8();
866 log_abc(" Flags: %X", flags | 0x0);
867 // log_abc("Check if flags and optional args.");
868 // If there are default parameters, read them now.
869 // Runtime will do validation of whether or not these can actually
870 // be assigned to the corresponding parameters.
871 if (flags & METHOD_OPTIONAL_ARGS) {
872
873 boost::uint32_t ocount = _stream->read_V32();
874 log_abc(" Optional args: %u", ocount);
875 pMethod->setMinArgumentCount(pMethod->maxArgumentCount() - ocount);
876
877 for (unsigned int j = 0; j < ocount; ++j) {
878 log_abc(" Reading optional arg: %u", j);
879 boost::uint32_t index = _stream->read_V32();
880
881 PoolConstant kindof =
882 static_cast<PoolConstant>(_stream->read_u8());
883
884 log_abc(" Index: %u Kindof: %u", index, kindof);
885 as_value v;
886 if (!pool_value(index, kindof, v)) {
887 return false;
888 }
889 pMethod->pushOptional(v);
890 }
891 log_abc("Done handling optional args.");
892 }
893
894 if (flags & METHOD_ACTIVATION) {
895 log_abc("Method needs activation");
896 pMethod->setNeedsActivation();
897 }
898
899 // If there are names present for the parameters, skip them.
900 if (flags & METHOD_ARG_NAMES) {
901 for (size_t j = 0; j < param_count; ++j) {
902 _stream->skip_V32();
903 }
904 }
905 } // End of method loop.
906 return true;
907 }
908
909 /// Skip the metadata, which is useless to us.
910 bool
911 AbcBlock::skip_metadata()
912 {
913 boost::uint32_t count = _stream->read_V32();
914 for (unsigned int i = 0; i < count; ++i)
915 {
916 _stream->skip_V32(); // A name index.
917 boost::uint32_t icount = _stream->read_V32();
918 for (unsigned int j = 0; j < icount; ++j)
919 {
920 // key/values may not be stored together, but this still works.
921 _stream->skip_V32();
922 _stream->skip_V32();
923 }
924 }
925 return true;
926 }
927
928 /// Load the instances from the block.
929 bool
930 AbcBlock::read_instances()
931 {
932 boost::uint32_t count = _stream->read_V32();
933 log_abc("There are %u instances.", count);
934 _classes.resize(count);
935 for (size_t i = 0; i < count; ++i) {
936 //Read multiname index.
937 boost::uint32_t index = _stream->read_V32();
938 // 0 is allowed as a name, typically for the last entry.
939 if (index >= _multinamePool.size()) {
940 log_error(_("ABC: Out of bounds instance name."));
941 return false;
942 }
943
944 MultiName& multiname = _multinamePool[index];
945
946 // This must be a QName.
947 if (!multiname.isQName()) {
948 log_error(_("ABC: QName required for instance."));
949 return false;
950 }
951
952 if (!multiname.getNamespace()) {
953 log_error(_("ABC: No namespace to use for storing class."));
954 return false;
955 }
956
957 abc::Class* cl = locateClass(multiname);
958
959 if (!cl) {
960
961 const string_table::key className = multiname.getGlobalName();
962
963 cl = mCH->newClass();
964 cl->setName(className);
965
966 if (!multiname.getNamespace()->addScript(className, cl)) {
967
968 log_error(_("Duplicate class registration."));
969 return false;
970 }
971 log_debug("Adding class %s (%s) to namespace %s",
972 _stringTable->value(multiname.getGlobalName()),
973 _stringPool[multiname.getABCName()],
974 _stringTable->value(multiname.getNamespace()->getURI()));
975 log_debug("Namespace now:");
976 multiname.getNamespace()->dump(*_stringTable);
977
978 }
979 cl->setDeclared();
980 _classes[i] = cl;
981 boost::uint32_t super_index = _stream->read_V32();
982
983 if (super_index && super_index >= _multinamePool.size()) {
984 log_error(_("ABC: Bad super type."));
985 return false;
986 }
987
988 if (!super_index) {
989 cl->setSuper(mTheObject);
990 }
991 else {
992 abc::Class *pSuper = locateClass(_multinamePool[super_index]);
993 if (!pSuper)
994 {
995 log_error(_("ABC: Super type not found (%s)"),
996 _stringPool[_multinamePool[super_index].getABCName()]);
997 return false;
998 }
999
1000 if (pSuper->isFinal())
1001 {
1002 log_error(_("ABC: Can't extend a class which is final."));
1003 return false;
1004 }
1005
1006 if (pSuper->isInterface())
1007 {
1008 log_error(_("ABC: Can't extend an interface type."));
1009 return false;
1010 }
1011
1012 if (pSuper == cl)
1013 {
1014 log_error(_("ABC: Class cannot be its own supertype."));
1015 return false;
1016 }
1017 cl->setSuper(pSuper);
1018 pSuper->setInherited();
1019 }
1020
1021 boost::uint8_t flags = _stream->read_u8();
1022 log_abc("Instance %u(%s) multiname index=%u name=%s super index=%u "
1023 "flags=%X", i, cl, index,
1024 _stringPool[_multinamePool[index].getABCName()],
1025 super_index, flags | 0x0);
1026
1027 if (flags & INSTANCE_SEALED) cl->setSealed();
1028 if (flags & INSTANCE_FINAL) cl->setFinal();
1029 if (flags & INSTANCE_INTERFACE) cl->setInterface();
1030 if ((flags & 7) == INSTANCE_DYNAMIC) cl->setDynamic();
1031
1032 if (flags & INSTANCE_PROTECTED_NS) {
1033 boost::uint32_t ns_index = _stream->read_V32();
1034 if (ns_index >= _namespacePool.size()) {
1035 log_error(_("ABC: Bad namespace for protected."));
1036 return false;
1037 }
1038 // Set the protected namespace's parent, if it exists.
1039 if (cl->getSuper()->hasProtectedNs())
1040 _namespacePool[ns_index]->setParent(
1041 cl->getSuper()->getProtectedNs());
1042 cl->setProtectedNs(_namespacePool[ns_index]);
1043 }
1044
1045 // This is the list of interfaces which the instances has agreed to
1046 // implement. They must be interfaces, and they must exist.
1047 boost::uint32_t intcount = _stream->read_V32();
1048 log_abc("This instance has %u interfaces.", intcount);
1049 for (size_t j = 0; j < intcount; ++j) {
1050 boost::uint32_t i_index = _stream->read_V32();
1051 log_abc("Interface %u has multiname index=%u", i, i_index);
1052 // 0 is allowed as an interface, typically for the last one.
1053 if (i_index >= _multinamePool.size()) {
1054 log_error(_("ABC: Bad name for interface."));
1055 return false;
1056 }
1057 abc::Class *pInterface = locateClass(_multinamePool[i_index]);
1058 // These may be undefined still, so don't check interface just yet.
1059 if (0) //!pInterface || !pInterface->isInterface())
1060 {
1061 log_error(_("ABC: Can't implement a non-interface type."));
1062 return false;
1063 }
1064 cl->pushInterface(pInterface);
1065 }
1066
1067 // The next thing should be the constructor.
1068 // TODO: What does this mean exactly? How does it differ from the one in
1069 // the class info block?
1070 boost::uint32_t offset = _stream->read_V32();
1071 log_abc("Moffset: %u", offset);
1072 if (offset >= _methods.size()) {
1073 log_error(_("ABC: Out of bounds method for initializer."));
1074 return false;
1075 }
1076 // Don't validate for previous owner.
1077 cl->setConstructor(_methods[offset]);
1078
1079 // Next come the 'traits' of the instance. (The members.)
1080 boost::uint32_t tcount = _stream->read_V32();
1081 log_abc("Trait count: %u", tcount);
1082 for (unsigned int j = 0; j < tcount; ++j)
1083 {
1084 Trait t;
1085 t.set_target(cl, false);
1086 if (!t.read(_stream, this)) return false;
1087 cl->addInstanceTrait(t);
1088 }
1089 }
1090 return true;
1091 }
1092
1093 /// Read the class data
1094 bool
1095 AbcBlock::read_classes()
1096 {
1097 // Count was found in read_instances().
1098 log_abc("Begin reading classes.");
1099 boost::uint32_t count = _classes.size();
1100 log_abc("There are %u classes.", count);
1101
1102 for (size_t i = 0; i < count; ++i) {
1103 abc::Class* cl = _classes[i];
1104 boost::uint32_t offset = _stream->read_V32();
1105 log_abc("Class %u(%s) static constructor index=%u", i, cl, offset);
1106
1107 if (offset >= _methods.size()) {
1108 log_error(_("ABC: Out of bound static constructor for class."));
1109 return false;
1110 }
1111
1112 // Don't validate for previous owner.
1113 cl->setStaticConstructor(_methods[offset]);
1114
1115 boost::uint32_t tcount = _stream->read_V32();
1116 log_abc("This class has %u traits.", tcount);
1117 for (size_t j = 0; j < tcount; ++j) {
1118 Trait t;
1119 t.set_target(cl, true);
1120 if (!(t.read(_stream, this))) return false;
1121 cl->addStaticTrait(t);
1122 }
1123 }
1124 return true;
1125 }
1126
1127 /// Read the scripts (global functions)
1128 /// The final script is the entry point for the block.
1129 bool
1130 AbcBlock::read_scripts()
1131 {
1132 log_abc("Begin reading scripts.");
1133
1134 const boost::uint32_t scriptcount = _stream->read_V32();
1135 log_abc("There are %u scripts.", scriptcount);
1136
1137 _scripts.resize(scriptcount);
1138 for (size_t i = 0; i < scriptcount; ++i) {
1139
1140 abc::Class* script = mCH->newClass();
1141 _scripts[i] = script;
1142
1143 boost::uint32_t offset = _stream->read_V32();
1144 log_abc("Reading script %u(%s) initializer method index=%u", i,
1145 script, offset);
1146 if (offset >= _methods.size()) {
1147 log_error(_("ABC: Out of bounds method for script."));
1148 return false;
1149 }
1150
1151 script->setConstructor(_methods[offset]);
1152
1153 const boost::uint32_t tcount = _stream->read_V32();
1154 for (size_t j = 0; j < tcount; ++j) {
1155
1156 Trait t;
1157 t.set_target(script, false);
1158 if (!(t.read(_stream, this))) {
1159 return false;
1160 }
1161 log_abc("Trait: %u name: %s(%u) kind: %s value: %s ", j,
1162 _stringPool[t._name], t._name, t._kind, t._value);
1163
1164 // TODO: this should not use Class!
1165 script->addStaticTrait(t);
1166 }
1167 }
1168 return true;
1169 }
1170
1171 /// Read the method bodies and attach them to the methods.
1172 bool
1173 AbcBlock::read_method_bodies()
1174 {
1175 boost::uint32_t count = _stream->read_V32();
1176 log_abc("There are %u method bodies.", count);
1177 for (unsigned int i = 0; i < count; ++i)
1178 {
1179 boost::uint32_t offset = _stream->read_V32();
1180 log_abc("Method body %u method offset=%u", i, offset);
1181
1182 if (offset >= _methods.size()) {
1183 log_error(_("ABC: Out of bounds for method body."));
1184 return false;
1185 }
1186
1187 Method& method = *_methods[offset];
1188
1189 if (method.getBody()) {
1190 log_error(_("ABC: Only one body per method."));
1191 return false;
1192 }
1193
1194 // Maximum stack size.
1195 method.setMaxStack(_stream->read_V32());
1196
1197 // Maximum register size.
1198 method.setMaxRegisters(_stream->read_V32());
1199
1200 // Scope depth.
1201 method.setScopeDepth(_stream->read_V32());
1202
1203 // Max scope depth.
1204 method.setMaxScope(_stream->read_V32());
1205
1206 // Code length
1207 boost::uint32_t clength = _stream->read_V32();
1208 method.setBodyLength(clength);
1209
1210 // The code.
1211 //TODO: Clean this up.
1212 std::string body;
1213 _stream->read_string_with_length(clength, body);
1214
1215 method.setBody(new CodeStream(body));
1216
1217 // Exception count and exceptions
1218
1219 // Note: catch type and variable name are documented to be
1220 // indices in the string pool, but they are in fact indices
1221 // in the multiname pool.
1222 const boost::uint32_t ecount = _stream->read_V32();
1223 for (unsigned int j = 0; j < ecount; ++j) {
1224 asException *ex = mCH->newException();
1225
1226 // Where the try block begins and ends.
1227 ex->setStart(_stream->read_V32());
1228 ex->setEnd(_stream->read_V32());
1229
1230 // Where to go when the exception is activated.
1231 ex->setCatch(_stream->read_V32());
1232
1233 // What types should be caught.
1234 boost::uint32_t catch_type = _stream->read_V32();
1235 if (catch_type >= _multinamePool.size()) {
1236 log_error(_("ABC: Out of bound type for exception."));
1237 return false;
1238 }
1239 if (!catch_type) {
1240 ex->catchAny();
1241 }
1242 else {
1243 abc::Class *type = locateClass(_multinamePool[catch_type]);
1244 if (!type) {
1245
1246 log_error(_("ABC: Unknown type of object to catch. (%s)"),
1247 _stringTable->value(
1248 _multinamePool[catch_type].getABCName()));
1249
1250 // return false;
1251 // Fake it, for now:
1252 ex->catchAny();
1253 }
1254 else {
1255 ex->setCatchType(type);
1256 }
1257 }
1258
1259 // A variable name for the catch type.
1260 // In version 46.15, no names.
1261 if (mVersion != ((46 << 16) | 15)) {
1262 boost::uint32_t cvn = _stream->read_V32();
1263 if (cvn >= _multinamePool.size()) {
1264 log_error(_("ABC: Out of bound name for caught "
1265 "exception."));
1266 return false;
1267 }
1268 ex->setName(_multinamePool[cvn].getABCName());
1269 ex->setNamespace(_multinamePool[cvn].getNamespace());
1270 }
1271 }
1272
1273 // Traits
1274 boost::uint32_t tcount = _stream->read_V32();
1275 for (unsigned int j = 0; j < tcount; ++j)
1276 {
1277 Trait t;
1278 t.set_target(_methods[offset]);
1279
1280 if (!t.read(_stream, this)) {
1281 return false;
1282 }
1283
1284 log_abc("Activation trait: %u name: %s, kind: %s, value: %s ", j,
1285 _stringPool[t._name], t._kind, t._value);
1286 _methods[offset]->addTrait(t);
1287 }
1288 }
1289 return true;
1290 }
1291
1292 // Load up all of the data.
1293 bool
1294 AbcBlock::read(SWFStream& in)
1295 {
1296 // This isn't very nice:
1297 _stream = ∈
1298
1299 if (!read_version()) return false;
1300 if (!read_integer_constants()) return false;
1301 if (!read_unsigned_integer_constants()) return false;
1302 log_abc("Done reading unsigned integer constants.");
1303
1304 if (!read_double_constants()) return false;
1305 log_abc("Done reading double constants.");
1306
1307 if (!read_string_constants()) return false;
1308 log_abc("Done reading string constants.");
1309
1310 if (!read_namespaces()) return false;
1311 log_abc("Done reading namespaces.");
1312
1313 if (!read_namespace_sets()) return false;
1314 log_abc("Done reading namespace sets.");
1315
1316 if (!read_multinames()) return false;
1317 log_abc("Done reading multinames.");
1318
1319 if (!read_method_infos()) return false;
1320 log_abc("Done reading method infos.");
1321
1322 if (!skip_metadata()) return false;
1323 log_abc("Done reading metadata.");
1324
1325 if (!read_instances()) return false;
1326 log_abc("Done reading instances.");
1327
1328 if (!read_classes()) return false;
1329 log_abc("Done reading classes.");
1330
1331 if (!read_scripts()) return false;
1332 log_abc("Done reading scripts.");
1333
1334 if (!read_method_bodies()) return false;
1335 log_abc("Done reading stuff.");
1336
1337 for (size_t i=0; i < _methods.size(); ++i) {
1338 log_abc("Method %d body:", i);
1339 IF_VERBOSE_PARSE(_methods[i]->print_body());
1340 }
1341 return true;
1342 }
1343
1344
1345 void
1346 AbcBlock::update_global_name(unsigned int multiname_index)
1347 {
1348
1349 MultiName* multiname = &_multinamePool[multiname_index];
1350 string_table::key new_key =
1351 _stringTable->find(_stringPool[multiname->getABCName()], false);
1352 multiname->setGlobalName(new_key);
1353 }
1354
1355 std::ostream&
1356 operator<<(std::ostream& o, AbcBlock::NamespaceConstant c)
1357 {
1358 switch (c)
1359 {
1360 case AbcBlock::PRIVATE_NS:
1361 return o << "private namespace";
1362 case AbcBlock::CONSTANT_NS:
1363 return o << "constant namespace";
1364 case AbcBlock::PACKAGE_NS:
1365 return o << "package namespace";
1366 case AbcBlock::PACKAGE_INTERNAL_NS:
1367 return o << "package internal namespace";
1368 case AbcBlock::PROTECTED_NS:
1369 return o << "protected namespace";
1370 case AbcBlock::EXPLICIT_NS:
1371 return o << "explicit namespace";
1372 case AbcBlock::STATIC_PROTECTED_NS:
1373 return o << "static protected namespace";
1374 default:
1375 return o << "invalid namespace constant";
1376 }
1377 }
1378
1379 std::ostream&
1380 operator<<(std::ostream& o, AbcBlock::MethodConstant c)
1381 {
1382 switch (c)
1383 {
1384 case AbcBlock::METHOD_ARGS:
1385 return o << "method arg";
1386 case AbcBlock::METHOD_ACTIVATION:
1387 return o << "method activation";
1388 case AbcBlock::METHOD_MORE:
1389 return o << "method more";
1390 case AbcBlock::METHOD_OPTIONAL_ARGS:
1391 return o << "method optional args";
1392 case AbcBlock::METHOD_IGNORE:
1393 return o << "method ignore";
1394 case AbcBlock::METHOD_NATIVE:
1395 return o << "method native";
1396 case AbcBlock::METHOD_DEFAULT_NS:
1397 return o << "default namespace";
1398 case AbcBlock::METHOD_ARG_NAMES:
1399 return o << "method arg names";
1400 default:
1401 return o << "invalid method constant";
1402 }
1403 }
1404
1405 std::ostream&
1406 operator<<(std::ostream& o, AbcBlock::InstanceConstant c)
1407 {
1408 switch (c)
1409 {
1410 case AbcBlock::INSTANCE_SEALED:
1411 return o << "instance sealed";
1412 case AbcBlock::INSTANCE_FINAL:
1413 return o << "instance final";
1414 case AbcBlock::INSTANCE_INTERFACE:
1415 return o << "instance interface";
1416 case AbcBlock::INSTANCE_DYNAMIC:
1417 return o << "instance dynamic";
1418 case AbcBlock::INSTANCE_PROTECTED_NS:
1419 return o << "instance protected namespace";
1420 default:
1421 return o << "invalid instance constant";
1422 }
1423 }
1424
1425 std::ostream&
1426 operator<<(std::ostream& o, AbcBlock::PoolConstant c)
1427 {
1428 switch (c)
1429 {
1430 case AbcBlock::POOL_STRING:
1431 return o << "pool string";
1432 case AbcBlock::POOL_INTEGER:
1433 return o << "pool integer";
1434 case AbcBlock::POOL_UINTEGER:
1435 return o << "pool uinteger";
1436 case AbcBlock::POOL_DOUBLE:
1437 return o << "pool double";
1438 case AbcBlock::POOL_NAMESPACE:
1439 return o << "pool namespace";
1440 case AbcBlock::POOL_FALSE:
1441 return o << "pool false";
1442 case AbcBlock::POOL_TRUE:
1443 return o << "pool true";
1444 case AbcBlock::POOL_NULL:
1445 return o << "pool null";
1446 default:
1447 return o << "invalid pool constant";
1448
1449 }
1450 }
1451
1452 } // namespace abc
1453 } // namespace gnash
1454