Bug Summary

File:platform/mac/avmshell/../../../core/AbcParser.cpp
Location:line 528, column 17
Description:Value stored to 'earlyDispId' is never read

Annotated Source Code

1/* -*- Mode: C++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 4 -*- */
2/* vi: set ts=4 sw=4 expandtab: (add to ~/.vimrc: set modeline modelines=5) */
3/* ***** BEGIN LICENSE BLOCK *****
4 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
5 *
6 * The contents of this file are subject to the Mozilla Public License Version
7 * 1.1 (the "License"); you may not use this file except in compliance with
8 * the License. You may obtain a copy of the License at
9 * http://www.mozilla.org/MPL/
10 *
11 * Software distributed under the License is distributed on an "AS IS" basis,
12 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13 * for the specific language governing rights and limitations under the
14 * License.
15 *
16 * The Original Code is [Open Source Virtual Machine.].
17 *
18 * The Initial Developer of the Original Code is
19 * Adobe System Incorporated.
20 * Portions created by the Initial Developer are Copyright (C) 1993-2006
21 * the Initial Developer. All Rights Reserved.
22 *
23 * Contributor(s):
24 * Adobe AS3 Team
25 *
26 * Alternatively, the contents of this file may be used under the terms of
27 * either the GNU General Public License Version 2 or later (the "GPL"), or
28 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
29 * in which case the provisions of the GPL or the LGPL are applicable instead
30 * of those above. If you wish to allow use of your version of this file only
31 * under the terms of either the GPL or the LGPL, and not to allow others to
32 * use your version of this file under the terms of the MPL, indicate your
33 * decision by deleting the provisions above and replace them with the notice
34 * and other provisions required by the GPL or the LGPL. If you do not delete
35 * the provisions above, a recipient may use your version of this file under
36 * the terms of any one of the MPL, the GPL or the LGPL.
37 *
38 * ***** END LICENSE BLOCK ***** */
39
40#include "avmplus.h"
41
42namespace avmplus
43{
44 /**
45 * parse a .abc file completely
46 * @param code
47 * @return
48 */
49 PoolObject* AbcParser::decodeAbc(AvmCore* core, ScriptBuffer code,
50 Toplevel* toplevel,
51 Domain* domain,
52 const NativeInitializer* natives,
53 ApiVersion apiVersion)
54 {
55 int version;
56 int result = canParse(code, &version);
57
58#ifdef AVMPLUS_VERBOSE
59 if (core->isVerbose(VB_parse))
60 core->console << "major=" << (version&0xFFFF) << " minor=" << (version>>16) << "\n";
61#endif
62
63 if (result != 0) {
64 switch (result) {
65 case kInvalidMagicError:
66 toplevel->throwVerifyError(kInvalidMagicError, core->toErrorString(version>>16), core->toErrorString(version&0xFFFF));
67 case kCorruptABCError:
68 default:
69 toplevel->throwVerifyError(kCorruptABCError);
70 }
71 }
72
73#ifdef VMCFG_AOT
74 if(!natives) // no natives -- runtime-loaded script
75 {
76 if(version == 0 && code.getSize() == 24) // only ABC "references" -- these are 0.0 version followed by SHA1
77 {
78 void *sha1 = (void *)(code.getBuffer() + 4);
79 for(uint32_t i = 0; i < nAOTInfos; i++)
80 {
81 const AOTInfo *aotInfo = &aotInfos[i];
82 AvmAssert(aotInfo != NULL)do { } while (0);
83
84 MMGC_STATIC_ASSERT(sizeof(aotInfo->origABCSHA1) == 20)typedef ::MMgc::static_assert_MMgc<sizeof (::MMgc::STATIC_ASSERTION_FAILED
<(bool)(sizeof(aotInfo->origABCSHA1) == 20)>)> MMgc_static_assert_line_84
;
85 if(!memcmp(aotInfo->origABCSHA1, sha1, 20))
86 {
87 ScriptBuffer code = ScriptBuffer(new (core->GetGC()) ReadOnlyScriptBufferImpl(aotInfo->abcBytes, aotInfo->nABCBytes));
88
89 NativeInitializer ninit(core, NULL__null, aotInfo, 0, 0);
90 PoolObject *pool = decodeAbc(core, code, toplevel, domain, &ninit, apiVersion);
91 AvmAssert(pool != NULL)do { } while (0);
92 AvmAssert(!pool->isBuiltin)do { } while (0);
93 AvmAssert(pool->aotInfo == aotInfo)do { } while (0);
94#ifdef DEBUGGER
95 // TODO: is there a better pace to do this for both builtins and user scripts?
96 addAOTDebugInfo(pool);
97#endif
98 return pool;
99 }
100 }
101 }
102 toplevel->throwVerifyError( kCorruptABCError ); // not a reference or not found
103 return NULL__null;
104 }
105#endif
106
107 AbcParser parser(core, code, toplevel, domain, natives);
108 PoolObject *pObject = parser.parse(apiVersion);
109 if ( !pObject ) {
110 toplevel->throwVerifyError( kCorruptABCError );
111 /*NOTREACHED*/
112 return NULL__null;
113 }
114
115 // register this pool giving it a unique id based on MethodInfo count
116 core->assignPoolId(pObject);
117 return pObject;
118 }
119
120#if defined(VMCFG_AOT) && defined(DEBUGGER)
121 void AbcParser::addAOTDebugInfo(PoolObject *pool)
122 {
123 AvmCore *core = pool->core;
124 const AOTInfo *aotInfo = pool->aotInfo;
125 Debugger *debugger = core->debugger();
126
127 if(debugger)
128 {
129 const MethodDebugInfo* methodDebugInfos = aotInfo->methodDebugInfos;
130
131 if(methodDebugInfos != NULL__null)
132 {
133 // create the structure representing the ABC
134 AbcFile* abc = AbcFile::create(core->GetGC(), core, 0);
135
136 for(int n = 0; n < aotInfo->nABCMethods; n++)
137 {
138 MethodInfo *f = pool->getMethodInfo(n);
139
140 // create DMIs
141 const MethodDebugInfo &info = methodDebugInfos[n];
142 DebuggerMethodInfo* dmi = DebuggerMethodInfo::create(core, info.local_count, -1, info.scope_count);
143 pool->_method_dmi.set(n, dmi);
144
145 // set the file in the MethodInfo
146 f->setFile(abc);
147
148 // get a SourceFile
149 SourceFile *src = NULL__null;
150
151 if(info.file_name)
152 {
153 Stringp fileName = pool->getString(info.file_name);
154 src = abc->sourceNamed(fileName);
155 if(!src)
156 {
157 src = SourceFile::create(core->GetGC(), fileName);
158 abc->sourceAdd(src);
159 }
160 }
161
162 // set register names
163 for(int i = 0; i < info.local_count; i++)
164 {
165 int name = info.local_names[i];
166
167 if(name)
168 f->setRegName(i, pool->getString(name));
169 }
170
171 // add line info
172 if(src)
173 for(int i = 0; i < info.line_count; i++)
174 src->addLine(info.lines[i], f, 0);
175 }
176 // hook the ABC in
177 debugger->pool2abcIndex.add(pool, (const void *)debugger->abcList.length());
178 debugger->abcList.add(abc);
179 }
180 }
181 }
182#endif
183
184 int AbcParser::canParse(ScriptBuffer code, int* version)
185 {
186 if (version != NULL__null)
187 *version = 0;
188
189 if (code.getSize() < 4)
190 return kCorruptABCError;
191
192 int v = AvmCore::readU16(&code[0]) | AvmCore::readU16(&code[2])<<16;
193 if (version != NULL__null)
194 *version = v;
195
196 switch (v) {
197#ifdef VMCFG_AOT
198 case 0: // just a "reference" to an AOT-ed ABC!
199#endif
200 case (46<<16|16): // Original ABC version number
201#ifdef VMCFG_SWF12
202 case (47<<16|12): // Flash player TBD
203 return 0;
204#endif
205#ifdef VMCFG_SWF13
206 case (47<<16|13): // Flash player TBD
207 return 0;
208#endif
209#ifdef VMCFG_SWF14
210 case (47<<16|14): // Flash player TBD
211 return 0;
212#endif
213#ifdef VMCFG_SWF15
214 case (47<<16|15): // Flash player TBD
215 return 0;
216#endif
217#ifdef VMCFG_SWF16
218 case (47<<16|16): // Flash player TBD
219 return 0;
220#endif
221#ifdef VMCFG_SWF17
222 case (47<<16|17): // Flash player TBD
223 return 0;
224#endif
225#ifdef VMCFG_SWF18
226 case (47<<16|18): // Flash player TBD
227 return 0;
228#endif
229#ifdef VMCFG_SWF19
230 case (47<<16|19): // Flash player TBD
231 return 0;
232#endif
233#ifdef VMCFG_SWF20
234 case (47<<16|20): // Flash player TBD
235 return 0;
236#endif
237 default:
238 return kInvalidMagicError;
239 }
240 }
241
242 AbcParser::AbcParser(AvmCore* core, ScriptBuffer code,
243 Toplevel* toplevel,
244 Domain* domain,
245 const NativeInitializer* natives)
246 : instances(core->GetGC(), 0),
247 toplevel(toplevel),
248 domain(domain),
249 metaNames(core->GetGC(), 0)
250 {
251 this->core = core;
252 this->code = code;
253 this->pool = NULL__null;
254 this->version = AvmCore::readU16(&code[0]) | AvmCore::readU16(&code[2])<<16;
255 this->pos = &code[4];
256 this->natives = natives;
257
258 abcStart = &code[0];
259 abcEnd = &code[(int)code.getSize()];
260
261 classCount = 0;
262
263 // Default flag settings go here
264 floatSupport = 0;
265 float4Support = 0;
266
267 // Flag overrides based on version go here
268
269 if (this->version >= (47<<16|12)) {
270 // Flash Player Wasabi
271 }
272 if (this->version >= (47<<16|13)) {
273 // Flash Player Serrano
274 }
275 if (this->version >= (47<<16|14)) {
276 // Flash Player Anza
277 }
278 if (this->version >= (47<<16|15)) {
279 // Flash Player Brannan
280#ifdef VMCFG_FLOAT
281 floatSupport = 1;
282#endif
283#ifdef VMCFG_FLOAT4
284 float4Support = 1;
285#endif
286 }
287 if (this->version >= (47<<16|16)) {
288 // Flash Player Cyril
289 }
290 if (this->version >= (47<<16|17)) {
291 // Flash Player Dolores
292 }
293 if (this->version >= (47<<16|18)) {
294 // Flash Player Ellis
295 }
296 if (this->version >= (47<<16|19)) {
297 // Flash Player TBD
298 }
299 if (this->version >= (47<<16|20)) {
300 // Flash Player TBD
301 }
302 }
303
304 Namespacep AbcParser::parseNsRef(const uint8_t* &pc) const
305 {
306 uint32_t index = readU30(pc);
307 if (index == 0)
308 {
309 return NULL__null; // AnyNamespace
310 }
311
312 if (index >= pool->constantNsCount)
313 toplevel->throwVerifyError(kCpoolIndexRangeError, core->toErrorString(index), core->toErrorString(pool->constantNsCount));
314 return pool->cpool_ns[index];
315 }
316
317#if defined(VMCFG_AOT) || defined(AVMPLUS_VERBOSE)
318 void AbcParser::parseTypeName(const uint8_t* &pc, Multiname& m) const
319 {
320 // only save the type name for now. verifier will resolve to traits
321 uint32_t index = readU30(pc);
322 if (index == 0)
323 {
324 // type is *
325 m.setNamespace(core->getPublicNamespace(pool));
326 m.setName(core->kAsterisk);
327 return;
328 }
329
330 if (index >= pool->cpool_mn_offsets.length())
331 toplevel->throwVerifyError(kCpoolIndexRangeError, core->toErrorString(index), core->toErrorString(pool->cpool_mn_offsets.length()));
332
333 pool->parseMultiname(m, index);
334 }
335 #endif
336
337 uint32_t AbcParser::resolveBindingName(const uint8_t* &p, Multiname &m) const
338 {
339 uint32_t index = readU30(p);
340 if (index == 0 || index >= pool->cpool_mn_offsets.length())
341 toplevel->throwVerifyError(kCpoolIndexRangeError, core->toErrorString(index),
342 core->toErrorString(pool->cpool_mn_offsets.length()));
343 pool->resolveBindingNameNoCheck(index, m, toplevel);
344
345 // Only builtin traits names can have multiple namespaces, which are used as an implementation
346 // mechanism of the versioning API, and express multiple introducing versions.
347 if (m.isBinding() && (m.isQName() || pool->isBuiltin))
348 return index;
349 else
350 {
351 toplevel->throwVerifyError(kCpoolEntryWrongTypeError, core->toErrorString(index));
352 return 0; // not reached
353 }
354 }
355
356 MethodInfo* AbcParser::resolveMethodInfo(uint32_t index) const
357 {
358 const uint32_t c = pool->methodCount();
359 if (index >= c)
360 toplevel->throwVerifyError(kMethodInfoExceedsCountError, core->toErrorString(index), core->toErrorString(c));
361
362 MethodInfo* f = pool->getMethodInfo(index);
363 if (!f)
364 toplevel->throwVerifyError(kMethodInfoOrderError, core->toErrorString(index));
365
366 return f;
367 }
368
369 Stringp AbcParser::resolveUtf8(uint32_t index) const
370 {
371 if (index > 0 && index < pool->constantStringCount)
372 {
373 return pool->getString(index);
374 }
375 toplevel->throwVerifyError(kCpoolIndexRangeError, core->toErrorString(index), core->toErrorString(pool->constantStringCount));
376 return NULL__null;
377 }
378
379 Stringp AbcParser::parseName(const uint8_t* &pc) const
380 {
381 uint32_t index = readU30(pc);
382 if (index == 0)
383 return NULL__null;
384 return resolveUtf8(index);
385 }
386
387 PoolObject* AbcParser::parse(ApiVersion apiVersion)
388 {
389#ifdef VMCFG_LOOKUP_CACHE
390 // Loading a new ABC file always invalidates the lookup cache
391 core->invalidateLookupCache();
392#endif
393 // Loading a new ABC file always invalidates the traits cache(s)
394 core->tbCache()->flush();
395 core->tmCache()->flush();
396
397 // constant pool
398 parseCpool(apiVersion);
399
400 // parse all methodInfos in one pass. Nested functions must come before outer functions
401 parseMethodInfos();
402
403 // parse all metadataInfos - AVM+ doesn't care about this, so we are really just skipping them
404 parseMetadataInfos();
405
406 // parse classes. base classes must come first.
407 if (!parseInstanceInfos()) return NULL__null;
408
409 boolbool first = falsefalse;
410 if (CLASS_TYPE(core->traits.class_itraits) == NULL__null)
411 {
412 // if we haven't got types from the builtin file yet, do it now.
413 first = truetrue;
414 core->traits.initInstanceTypes(pool);
415
416 // register "void"
417 addNamedTraits(core->getPublicNamespace(kApiVersion_VM_ALLVERSIONS), VOID_TYPE(core->traits.void_itraits)->name(), VOID_TYPE(core->traits.void_itraits));
418 }
419
420 // type information about class objects
421 parseClassInfos();
422
423 if (first)
424 {
425 core->traits.initClassTypes(pool);
426 }
427
428 // scripts
429 if( !parseScriptInfos() ) return NULL__null;
430
431 // method bodies: code, exception info, and activation traits
432 parseMethodBodies();
433
434 return pool;
435 }
436
437 // check to see if we are trying to read past the file end or the beginning.
438 #define CHECK_POS(pos)do { if ((pos) < abcStart || (pos) >= abcEnd ) toplevel
->throwVerifyError(kCorruptABCError); } while (0)
do { if ((pos) < abcStart || (pos) >= abcEnd ) toplevel->throwVerifyError(kCorruptABCError); } while (0)
439
440 /**
441 * setting up a traits that extends another one. Two parser passes are required,
442 * one for sizing the traits object and the other for allocating it and filling
443 * it in.
444 */
445 Traits* AbcParser::parseTraits(uint16_t sizeofInstance,
446 uint16_t offsetofSlots,
447 Traits* base,
448 Namespacep ns,
449 Stringp name,
450 MethodInfo* script,
451 TraitsPosPtr traitsPos,
452 TraitsPosType posType,
453 Namespacep protectedNamespace,
454 boolbool makeFinal)
455 {
456 uint32_t nameCount = readU30(pos);
457
458 // Very generous check for nameCount being way too large.
459 if (nameCount > (uint32_t)(abcEnd - pos))
460 toplevel->throwVerifyError(kCorruptABCError);
461 // Interfaces cant't have base traits
462 if (posType == TRAITSTYPE_INTERFACE && base != NULL__null)
463 toplevel->throwVerifyError(kCannotExtendError, name, core->toErrorString(base));
464
465 #ifdef AVMPLUS_VERBOSE
466 if (pool->isVerbose(VB_parse))
467 core->console << " trait_count=" << nameCount << "\n";
468 #endif
469
470 Traits* traits = Traits::newTraits(pool, base, sizeofInstance,offsetofSlots , traitsPos, posType);
471 traits->set_names(ns, name);
472 traits->protectedNamespace = protectedNamespace;
473
474 for (uint32_t i=0; i < nameCount; i++)
475 {
476 Multiname mn;
477 const uint32_t qn_index = resolveBindingName(pos, mn);
478 Namespacep ns;
479 const NamespaceSet* nss;
480 if (mn.namespaceCount() > 1) {
481 nss = (NamespaceSet*) mn.getNsset();
482 ns = nss->nsAt(0);
483 }
484 else {
485 ns = mn.getNamespace();
486 nss = NamespaceSet::create(core->GetGC(), ns);
487 }
488 Stringp name = mn.getName();
489 CHECK_POS(pos)do { if ((pos) < abcStart || (pos) >= abcEnd ) toplevel
->throwVerifyError(kCorruptABCError); } while (0)
;
490 int tag = *pos++;
491 TraitKind kind = (TraitKind) (tag & 0x0f);
492
493 uint32_t class_index = 0;
494 uint32_t method_index = 0;
495 uint32_t slot_id = 0;
496 uint32_t value_index = 0;
497 uint32_t earlyDispId = 0;
498 boolbool needsDxns = falsefalse;
499#ifdef AVMPLUS_VERBOSE
500 Multiname typeName;
501#endif
502
503 // Read in the trait entry.
504 switch (kind)
505 {
506 case TRAIT_Slot:
507 case TRAIT_Const:
508 slot_id = readU30(pos); // slot id
509#ifdef AVMPLUS_VERBOSE
510 parseTypeName(pos, typeName);
511#else
512 readU30(pos);
513#endif
514 value_index = readU30(pos); // value index
515 if (value_index)
516 {
517 CHECK_POS(pos)do { if ((pos) < abcStart || (pos) >= abcEnd ) toplevel
->throwVerifyError(kCorruptABCError); } while (0)
;
518 pos += 1; // value_kind
519 }
520 break;
521 case TRAIT_Class:
522 readU30(pos); // slot id
523 class_index = readU30(pos);
524 break;
525 case TRAIT_Getter:
526 case TRAIT_Setter:
527 case TRAIT_Method:
528 earlyDispId = readU30(pos); // disp id
Value stored to 'earlyDispId' is never read
529 method_index = readU30(pos);
530 break;
531 default:
532 // unsupported traits type
533 toplevel->throwVerifyError(kUnsupportedTraitsKindError, core->toErrorString(kind));
534 }
535
536 const uint8_t* meta_pos = pos;
537 if (tag & ATTR_metadata)
538 {
539 const uint32_t metadataCount = readU30(pos);
540 for (uint32_t metadata = 0; metadata < metadataCount; ++metadata)
541 {
542 const uint32_t index = readU30(pos);
543 if (index >= pool->metadataCount)
544 toplevel->throwVerifyError(kCorruptABCError);
545 Stringp name = metaNames[index];
546 if (name == core->kNeedsDxns)
547 needsDxns = truetrue;
548 }
549 }
550
551 switch (kind)
552 {
553 case TRAIT_Slot:
554 case TRAIT_Const:
555 case TRAIT_Class:
556 {
557 if (script)
558 addNamedScript(nss, name, script);
559
560 if (kind == TRAIT_Class)
561 {
562 // get the class type
563 if (class_index >= classCount)
564 toplevel->throwVerifyError(kClassInfoExceedsCountError, core->toErrorString(class_index), core->toErrorString(classCount));
565
566 // class_index could be legal (<classCount) but pointing to
567 // to a class not yet parsed (>= pool->classCount()), so handle that case.
568 Traits* ctraits = class_index < pool->classCount() ? pool->getClassTraits(class_index) : NULL__null;
569 if (!ctraits)
570 toplevel->throwVerifyError(kClassInfoOrderError, core->toErrorString(class_index));
571
572 #ifdef AVMPLUS_VERBOSE
573 if (pool->isVerbose(VB_parse))
574 {
575 core->console << " " << traitNames[kind]
576 << " name=" << Multiname::Format(ns, name)
577 << " slot_id=" << slot_id
578 << " type=" << ctraits
579 << "\n";
580 }
581 #endif
582
583 if (script)
584 {
585 // promote instance type to the vm-wide type table.
586 // map type name to traits
587 addNamedTraits(nss, name, ctraits->itraits);
588 if (tag & ATTR_metadata)
589 {
590 ctraits->itraits->setMetadataPos(meta_pos);
591 }
592 }
593 else
594 {
595 if (tag & ATTR_metadata)
596 {
597 ctraits->setMetadataPos(meta_pos);
598 }
599 }
600 }
601 else
602 {
603 #ifdef AVMPLUS_VERBOSE
604 if (pool->isVerbose(VB_parse))
605 {
606 core->console << " " << traitNames[kind]
607 << " name=" << Multiname::Format(ns, name)
608 << " slot_id=" << slot_id
609 << " value_index=" << value_index
610 << " type=" << typeName
611 << "\n";
612 }
613 #endif
614 }
615 break;
616 }
617 case TRAIT_Getter:
618 case TRAIT_Setter:
619 case TRAIT_Method:
620 {
621 #ifdef AVMPLUS_VERBOSE
622 if (pool->isVerbose(VB_parse))
623 {
624 core->console << " " << traitNames[kind]
625 << " name=" << Multiname::Format(ns, name)
626 << " disp_id=" << earlyDispId << " (ignored)"
627 << " method_index=" << method_index
628 << " attr=" << ((tag&ATTR_final)?"final":"virtual");
629 if (tag&ATTR_override)
630 core->console << "|override";
631 core->console << "\n";
632 }
633 #endif
634
635 // id is unused here
636 MethodInfo* f = resolveMethodInfo(method_index);
637
638 if (core->config.methodNames)
639 {
640 pool->_method_name_indices.set(method_index, -int32_t(qn_index));
641 }
642
643 // since this function is ref'ed here, we know the receiver type.
644 if (!f->makeMethodOf(traits))
645 toplevel->throwVerifyError(kCorruptABCError);
646
647 f->setKind(kind); // sets the _isGetter/_isSetter flags
648 if ((tag & ATTR_final) || makeFinal)
649 f->setFinal();
650 if (tag & ATTR_override)
651 f->setOverride();
652 if (needsDxns)
653 f->setNeedsDxns();
654
655 // only export one name for an accessor
656 // (note that addNamedScript checks for redundancy internally,
657 // no need to do so here)
658 if (script)
659 addNamedScript(nss, name, script);
660
661 break;
662 }
663
664 default:
665 // unsupported traits type
666 toplevel->throwVerifyError(kUnsupportedTraitsKindError, core->toErrorString(kind));
667 }
668
669#ifdef AVMPLUS_VERBOSE
670 if (tag & ATTR_metadata)
671 {
672 uint32_t metadataCount = readU30(meta_pos);
673 for (uint32_t metadata = 0; metadata < metadataCount; ++metadata)
674 {
675 uint32_t index = readU30(meta_pos);
676 if (pool->isVerbose(VB_parse))
677 core->console << " [" << metaNames[index] << "]\n";
678 }
679 }
680#endif
681 }
682
683 if (makeFinal)
684 traits->final = truetrue;
685 traits->verifyBindings(toplevel);
686 return traits;
687 }
688
689 void AbcParser::parseMethodInfos()
690 {
691 int methodCount = readU30(pos);
692
693 #ifdef AVMPLUS_VERBOSE
694 if(pool->isVerbose(VB_parse)) {
695 core->console << "method_count=" << methodCount << "\n";
696 }
697 #endif
698
699 int size = methodCount == 0 ? 1 : methodCount;
700
701 if (size > (abcEnd - pos))
702 toplevel->throwVerifyError(kCorruptABCError);
703
704 MMGC_MEM_TYPE(pool);
705 pool->_methods.ensureCapacity(size);
706#ifdef DEBUGGER
707 if (core->debugger())
708 {
709 pool->_method_dmi.ensureCapacity(size);
710 for (int i = 0; i < size; ++i)
711 pool->_method_dmi.set(i, NULL__null);
712 }
713#endif
714 if (core->config.methodNames)
715 {
716 pool->_method_name_indices.ensureCapacity(size);
717 }
718
719#ifdef AVMPLUS_VERBOSE
720 const uint8_t* startpos = pos;
721#endif
722
723 for (int i=0; i < methodCount; i++)
724 {
725#ifdef AVMPLUS_VERBOSE
726 int offset = (int)(pos-startpos);
727#endif
728 const uint8_t* info_pos = pos;
729
730 // MethodInfo
731 const int param_count = readU30(pos);
732
733#ifdef VMCFG_AOT
734 const uint8_t* ret_type_pos = pos;
735#endif
736
737 // @todo -- we should add an AbcParser equivalent of skipU32;
738 // then the next two clauses would be
739 // skipU32(pos, param_count+1);
740 // in non-verbose builds
741 #ifdef AVMPLUS_VERBOSE
742 Multiname returnTypeName;
743 parseTypeName(pos, returnTypeName);
744 if(pool->isVerbose(VB_parse)) {
745 core->console << " " << offset << ":method["<<i<<"]\n"
746 << " returnType=" << returnTypeName << "\n"
747 << " param_count=" << param_count
748 << "\n";
749 }
750 #else
751 readU30(pos);// return type name
752 #endif
753
754 for( int j = 1; j <= param_count; ++j)
755 {
756 #ifdef AVMPLUS_VERBOSE
757 Multiname multiname;
758 parseTypeName(pos, multiname);
759 if(pool->isVerbose(VB_parse)) {
760 core->console << " paramType["<<j<<"]="<< multiname << "\n";
761 }
762 #else
763 readU30(pos);
764 #endif
765 }
766
767 uint32_t name_index = readU30(pos);
768 (void)name_index;
769 CHECK_POS(pos)do { if ((pos) < abcStart || (pos) >= abcEnd ) toplevel
->throwVerifyError(kCorruptABCError); } while (0)
;
770 uint8_t abcFlags = *pos++;
771
772 #ifdef AVMPLUS_VERBOSE
773 if(pool->isVerbose(VB_parse)) {
774 core->console << " name_index=" << name_index;
775 if (name_index > 0 && name_index < pool->constantStringCount)
776 core->console << " \"" << pool->getString(name_index) << "\"";
777 core->console << "\n flags=" << (uint32_t)abcFlags << "\n";
778 }
779 #endif
780
781 const NativeMethodInfo* ni = NULL__null;
782 if (abcFlags & abcMethod_NATIVE)
783 {
784 ni = natives ? natives->getNativeInfo(i) : NULL__null;
785#ifdef VMCFG_VERIFYALL
786 if (core->config.verifyonly) {
787 // if it has native methods then treat it as builtin
788 pool->isBuiltin = truetrue;
789 }
790 else
791#endif
792 if (!ni) {
793 if (pool->isBuiltin) {
794 // If this assert hits, you're missing a native method. Method "i"
795 // corresponds to the function of the same number in
796 // source\avmglue\avmglue.h if you're running the Flash player.
797 AvmAssertMsg(0, "missing native method decl")do { } while (0);
798 }
799 toplevel->throwVerifyError(kIllegalNativeMethodError);
800 }
801 }
802
803#ifdef VMCFG_AOT
804 boolbool isCompiled = falsefalse;
805 AvmThunkNativeHandler handler;
806 // NativeMethodInfo.handler is a union of
807 // pointer to function and pointer to member function.
808 // Zero the structure so that the entire thing is
809 // initialized.
810 // See bugzilla#647660
811 NativeMethodInfo compiledMethodInfo = {0};
812 {
813 Multiname returnTypeName;
814 parseTypeName(ret_type_pos, returnTypeName);
815 if (!ni && natives->getCompiledInfo(&compiledMethodInfo, &handler, returnTypeName, i))
816 {
817 ni = &compiledMethodInfo;
818 isCompiled = truetrue;
819 }
820 }
821#endif
822
823 const int optional_count = (abcFlags & abcMethod_HAS_OPTIONAL) ? readU30(pos) : 0;
824
825 MethodInfo* info = MethodInfo::create(core->GetGC(), i, pool, info_pos, abcFlags, ni);
826
827#ifdef VMCFG_AOT
828 if (isCompiled)
829 info->setAotCompiled(handler);
830#endif
831
832 if (core->config.methodNames)
833 {
834 pool->_method_name_indices.set(i, int32_t(name_index));
835 }
836
837 if (abcFlags & abcMethod_HAS_OPTIONAL)
838 {
839 for( int j = 0; j < optional_count; ++j)
840 {
841 readU30(pos);
842 ++pos; // Kind bytes for each default value
843 }
844
845 if (!optional_count || (optional_count > param_count))
846 {
847 // cannot have more optional params than total params
848 toplevel->throwVerifyError(kCorruptABCError);
849 }
850 }
851
852 if (abcFlags & abcMethod_HAS_PARAM_NAMES)
853 {
854 // AVMPlus doesn't care about the param names, just skip past them
855 for( int j = 0; j < param_count; ++j )
856 {
857 readU30(pos);
858 }
859 }
860
861 // save method info pointer. we will verify code later.
862 pool->_methods.set(i, info);
863#ifdef DEBUGGER
864 // don't create the corresponding DebuggerMethodInfo yet, we'll do that in parseMethodBodies
865#endif
866 }
867 }
868
869
870 void AbcParser::parseMetadataInfos()
871 {
872 uint32_t metadataCount = readU30(pos);
873
874 #ifdef AVMPLUS_VERBOSE
875 if(pool->isVerbose(VB_parse)) {
876 core->console << "metadata_count=" << metadataCount << "\n";
877 }
878 #endif
879
880 if (metadataCount > uint32_t(abcEnd - pos))
881 toplevel->throwVerifyError(kCorruptABCError);
882
883 pool->metadata_infos.ensureCapacity(metadataCount);
884 pool->metadataCount = metadataCount;
885
886 if (metadataCount > 0)
887 {
888 metaNames.ensureCapacity(metadataCount-1); // Pre-size the list
889
890 for (uint32_t i=0; i < metadataCount; i++)
891 {
892 pool->metadata_infos.set(i, pos);
893 // MetadataInfo
894 uint32_t index = readU30(pos);
895 Stringp name = resolveUtf8(index);
896 metaNames.set(i, name);
897
898 #ifdef AVMPLUS_VERBOSE
899 if(pool->isVerbose(VB_parse)) {
900 core->console << " " << name;
901 }
902 #endif
903
904 int values_count = readU30(pos);
905 if (values_count > 0)
906 {
907 #ifdef AVMPLUS_VERBOSE
908 if(pool->isVerbose(VB_parse)) {
909 core->console << "(";
910 }
911 #endif
912 for(int q = 0; q < values_count; ++q)
913 {
914 uint32_t a = readU30(pos);
915 uint32_t b = readU30(pos);
916 #ifdef AVMPLUS_VERBOSE
917 if(pool->isVerbose(VB_parse)) {
918 core->console << a << "," << b;
919 if (q+1 < values_count)
920 core->console << " ";
921 }
922 #else
923 (void)a;
924 (void)b;
925 #endif
926 }
927 #ifdef AVMPLUS_VERBOSE
928 if(pool->isVerbose(VB_parse)) {
929 core->console << ")";
930 }
931 #endif
932 }
933 #ifdef AVMPLUS_VERBOSE
934 if(pool->isVerbose(VB_parse)) {
935 core->console << "\n";
936 }
937 #endif
938 }
939 }
940 }
941
942 void AbcParser::parseMethodBodies()
943 {
944 int bodyCount = readU30(pos);
945
946 #ifdef AVMPLUS_VERBOSE
947 if(pool->isVerbose(VB_parse)) {
948 core->console << "bodies_count=" << bodyCount << "\n";
949 }
950 #endif
951
952#ifdef AVMPLUS_VERBOSE
953 const uint8_t* startpos = pos;
954#endif
955
956 for (int i=0; i < bodyCount; i++)
957 {
958#ifdef AVMPLUS_VERBOSE
959 int offset = (int)(pos-startpos);
960#endif
961
962 uint32_t method_index = readU30(pos);
963 MethodInfo* info = resolveMethodInfo(method_index);
964
965 const uint8_t *body_pos = pos;
966
967 int max_stack = readU30(pos);
968 (void)max_stack;
969
970 int local_count = readU30(pos);
971 (void)local_count;
972
973 // can't do this check here because param_count isn't available
974 // until the method is resolved. (we could do some tricks to extract
975 // it, but we just defer this check to Verifier::verify instead.)
976 //if (local_count < info->param_count()+1)
977 //{
978 // // must have enough locals to hold all parameters including this
979 // toplevel->throwVerifyError(kCorruptABCError);
980 //}
981
982 // TODO change file format, just want local max_scope
983 int init_scope_depth = readU30(pos);
984 (void)init_scope_depth;
985
986 int max_scope_depth = readU30(pos);
987 (void)max_scope_depth;
988
989 int code_length = readU30(pos);
990
991 if (code_length <= 0
992#ifdef VMCFG_AOT
993 && !info->needActivation() // AOT allows a dummy body so that it can represent activation traits
994#endif
995 )
996 {
997 toplevel->throwVerifyError(kInvalidCodeLengthError, core->toErrorString(code_length));
998 }
999
1000 // check to see if we are trying to jump past the file end or the beginning.
1001 if ( pos < abcStart || pos+code_length >= abcEnd )
1002 toplevel->throwVerifyError(kCorruptABCError);
1003 pos += code_length;
1004
1005 int exception_count = readU30(pos);
1006
1007 #ifdef AVMPLUS_VERBOSE
1008 if(pool->isVerbose(VB_parse)) {
1009 core->console << " " << offset << ":method["<<method_index<<"] max_stack=" << max_stack
1010 << " local_count=" << local_count
1011 << " init_scope_depth=" << init_scope_depth
1012 << " max_scope_depth=" << max_scope_depth
1013 << " code_length=" << code_length
1014 << " exception_count=" << exception_count
1015 << "\n";
1016 }
1017 #endif
1018
1019 if (exception_count != 0)
1020 {
1021 info->setHasExceptions();
1022 for (int i=0; i<exception_count; i++)
1023 {
1024 // this will be parsed when method is verified.
1025 // see MethodInfo::resolveSignature
1026
1027 #ifdef AVMPLUS_VERBOSE
1028 int from = readU30(pos);
1029 int to = readU30(pos);
1030 int target = readU30(pos);
1031 Multiname typeName;
1032 parseTypeName(pos, typeName);
1033
1034 Multiname qn;
1035 uint32_t name_index = (version != (46<<16|15)) ? readU30(pos) : 0;
1036 if (name_index != 0)
1037 {
1038 if (name_index >= pool->cpool_mn_offsets.length())
1039 toplevel->throwVerifyError(kCpoolIndexRangeError, core->toErrorString(name_index), core->toErrorString(pool->constantCount));
1040 pool->parseMultiname(qn, name_index);
1041 }
1042
1043 if (pool->isVerbose(VB_parse))
1044 {
1045 core->console << " exception["<<i<<"] from="<< from
1046 << " to=" << to
1047 << " target=" << target
1048 << " type=" << typeName
1049 << " name=";
1050 if (name_index)
1051 {
1052 core->console << qn;
1053 }
1054 else
1055 {
1056 core->console << "(none)";
1057 }
1058 core->console << "\n";
1059 }
1060 #else
1061 readU30(pos); // from
1062 readU30(pos); // to
1063 readU30(pos); // target
1064 readU30(pos); // type name
1065 if (version != (46<<16|15))
1066 {
1067 const uint32_t name_index = readU30(pos); // variable name
1068 if (name_index >= pool->cpool_mn_offsets.length())
1069 toplevel->throwVerifyError(kCpoolIndexRangeError, core->toErrorString(name_index), core->toErrorString(pool->constantCount));
1070 }
1071 #endif
1072 }
1073 }
1074
1075 if (info->hasMethodBody())
1076 {
1077 // Interface methods should not have bodies
1078 Traits* declaringTraits = info->declaringTraits();
1079 if (declaringTraits && declaringTraits->isInterface())
1080 {
1081 toplevel->throwVerifyError(kIllegalInterfaceMethodBodyError, core->toErrorString(info));
1082 }
1083
1084#ifdef DEBUGGER
1085 if (core->debugger())
1086 {
1087 DebuggerMethodInfo* dmi = DebuggerMethodInfo::create(core, local_count, code_length, max_scope_depth - init_scope_depth);
1088 pool->_method_dmi.set(method_index, dmi);
1089 }
1090#endif
1091
1092 // if non-zero, we have a duplicate method body - throw a verify error
1093 if (info->abc_body_pos())
1094 {
1095 toplevel->throwVerifyError(kDuplicateMethodBodyError, core->toErrorString(info));
1096 }
1097
1098 AvmAssert(!info->isResolved())do { } while (0);
1099 info->set_abc_body_pos(body_pos);
1100
1101 // there will be a traits_count here, even if abcMethod_NEED_ACTIVATION is not
1102 // set. So we parse the same way all the time. We could reduce file size and
1103 // memory by omitting the count + traits completely.
1104
1105 const uint8_t* traits_pos = pos;
1106 int nameCount = readU30(pos);
1107 if (info->needActivation() || nameCount > 0)
1108 {
1109 pos = traits_pos;
1110 Namespacep ns = NULL__null;
1111 Stringp name = NULL__null;
1112 #ifdef AVMPLUS_VERBOSE
1113 if (core->config.methodNames)
1114 {
1115 ns = core->getPublicNamespace(pool);
1116 name = core->internString(info->getMethodNameWithTraits(declaringTraits));
1117 }
1118 #endif
1119 // activation traits are raw types, not subclasses of object. this is
1120 // okay because they aren't accessable to the programming model.
1121 Traits* act = parseTraits(sizeof(ScriptObject),
1122 sizeof(ScriptObject),
1123 NULL__null,
1124 ns,
1125 name,
1126 NULL__null,
1127 traits_pos,
1128 TRAITSTYPE_ACTIVATION,
1129 NULL__null);
1130 info->init_activationTraits(act);
1131 }
1132 else
1133 {
1134 // TODO remove this assert once abc format is adjusted
1135 AvmAssert(nameCount == 0)do { } while (0);
1136 }
1137 }
1138 else
1139 {
1140#ifdef VMCFG_AOT
1141 if (info->needActivation())
1142 {
1143 Namespacep ns = NULL__null;
1144 Stringp name = NULL__null;
1145 #ifdef AVMPLUS_VERBOSE
1146 if (core->config.methodNames)
1147 {
1148 ns = core->getPublicNamespace(pool);
1149 name = core->internString(info->getMethodNameWithTraits(info->declaringTraits()));
1150 }
1151 #endif
1152 // activation traits are raw types, not subclasses of object. this is
1153 // okay because they aren't accessable to the programming model.
1154 Traits* act = parseTraits(sizeof(ScriptObject),
1155 sizeof(ScriptObject),
1156 NULL__null,
1157 ns,
1158 name,
1159 NULL__null,
1160 pos,
1161 TRAITSTYPE_ACTIVATION,
1162 NULL__null);
1163 info->init_activationTraits(act);
1164 pool->aotInfo->activationTraits[method_index] = act;
1165 } else
1166#endif
1167 {
1168 // native methods should not have bodies!
1169 toplevel->throwVerifyError(kIllegalNativeMethodBodyError, core->toErrorString(info));
1170 }
1171 }
1172 }
1173 }
1174
1175 void AbcParser::parseCpool(ApiVersion apiVersion)
1176 {
1177 pool = PoolObject::create(core, code, pos, apiVersion);
1178 pool->domain = domain;
1179
1180#ifdef VMCFG_AOT
1181 AvmAssert(natives != 0)do { } while (0);
1182 pool->isBuiltin = natives->hasBuiltins();
1183 pool->aotInfo = natives->get_aotInfo();
1184#else
1185 pool->isBuiltin = (natives != NULL__null);
1186#endif
1187
1188 uint32_t int_count = readU30(pos);
1189 // sanity check to prevent huge allocations
1190 if (int_count > (uint32_t)(abcEnd - pos))
1191 toplevel->throwVerifyError(kCorruptABCError);
1192
1193 DataList<int32_t>& cpool_int = pool->cpool_int;
1194 cpool_int.ensureCapacity(int_count);
1195 pool->constantIntCount = int_count;
1196
1197#ifdef AVMPLUS_VERBOSE
1198 pool->verbose_vb = core->config.verbose_vb; // pool picks up global settings
1199#endif
1200
1201#ifdef AVMPLUS_VERBOSE
1202 const uint8_t* startpos = pos;
1203#endif
1204
1205 for(uint32_t i = 1; i < int_count; ++i)
1206 {
1207#ifdef AVMPLUS_VERBOSE
1208 int offset = (int)(pos-startpos);
1209#endif
1210 // S32 value
1211 cpool_int.set(i, readS32(pos));
1212 #ifdef AVMPLUS_VERBOSE
1213 if(pool->isVerbose(VB_parse)) {
1214 core->console << " " << offset << ":" << "cpool_int["<<(uint32_t)i<<"]="
1215 <<constantNames[CONSTANT_Int] << " ";
1216 core->console << cpool_int[i] << "\n";
1217 }
1218 #endif
1219 }
1220
1221 uint32_t uint_count = readU30(pos);
1222 if (uint_count > (uint32_t)(abcEnd - pos))
1223 toplevel->throwVerifyError(kCorruptABCError);
1224
1225 DataList<uint32_t>& cpool_uint = pool->cpool_uint;
1226 cpool_uint.ensureCapacity(uint_count);
1227 pool->constantUIntCount = uint_count;
1228
1229#ifdef AVMPLUS_VERBOSE
1230 startpos = pos;
1231#endif
1232
1233 for(uint32_t i = 1; i < uint_count; ++i)
1234 {
1235#ifdef AVMPLUS_VERBOSE
1236 int offset = (int)(pos-startpos);
1237#endif
1238 // U32 value
1239 cpool_uint.set(i, (unsigned)readS32(pos));
1240
1241 #ifdef AVMPLUS_VERBOSE
1242 if(pool->isVerbose(VB_parse)) {
1243 core->console << " " << offset << ":" << "cpool_uint["<<i<<"]="
1244 <<constantNames[CONSTANT_UInt] << " ";
1245 core->console << (double)cpool_uint[i];
1246 core->console << "\n";
1247 }
1248 #endif
1249 }
1250
1251 uint32_t double_count = readU30(pos);
1252 if (double_count > (uint32_t)(abcEnd - pos))
1253 toplevel->throwVerifyError(kCorruptABCError);
1254
1255 GCList<GCDouble>& cpool_double = pool->cpool_double;
1256 cpool_double.ensureCapacity(double_count);
1257 pool->constantDoubleCount = double_count;
1258
1259#ifdef AVMPLUS_VERBOSE
1260 startpos = pos;
1261#endif
1262
1263 for(uint32_t i = 1; i < double_count; ++i)
1264 {
1265#ifdef AVMPLUS_VERBOSE
1266 int offset = (int)(pos-startpos);
1267#endif
1268 double value = readDouble(pos);
1269 cpool_double.set(i, (GCDouble*)(core->allocDouble(value)&~7));
1270 #ifdef AVMPLUS_VERBOSE
1271 if(pool->isVerbose(VB_parse)) {
1272 core->console << " " << offset << ":" << "cpool_double["<<i<<"]="
1273 <<constantNames[CONSTANT_Double] << " ";
1274 core->console << value;
1275 core->console << "\n";
1276 }
1277 #endif
1278 }
1279
1280 uint32_t string_count = readU30(pos);
1281 if (string_count > (uint32_t)(abcEnd - pos))
1282 toplevel->throwVerifyError(kCorruptABCError);
1283
1284 MMGC_MEM_TYPE(pool);
1285 pool->setupConstantStrings(string_count);
1286
1287#ifdef AVMPLUS_VERBOSE
1288 startpos = pos;
1289#endif
1290
1291 pool->_abcStringStart = pos;
1292
1293 ConstantStringData* dataP = pool->_abcStrings->data;
1294 AvmAssert(core->kEmptyString != NULL)do { } while (0);
1295 dataP->str = core->kEmptyString;
1296 for(uint32_t i = 1; i < string_count; ++i)
1297 {
1298#ifdef AVMPLUS_VERBOSE
1299 int offset = (int)(pos-startpos);
1300#endif
1301 // save the uint8_t position into the cpool array
1302 (++dataP)->abcPtr = pos;
1303 // number of characters
1304 // todo - is compiler emitting no. of chars or no. of bytes?
1305
1306 // don't call readU30(), as it can throw. call readU32 and sanity-check ourself here.
1307 uint32_t len = AvmCore::readU32(pos);
1308
1309 // check to see if we are trying to read past the file end or the beginning.
1310 // FIXME: bug #545652, should check if UTF8 is valid, skipping for compatibility.
1311 if ((len & 0xc0000000) || pos < abcStart || pos+len >= abcEnd)
1312 {
1313 // if we throw a verify error here, _abcStringEnd will never be set, and _abcStrings
1314 // will be left in an inconsistent state. having _abcStringStart set but not _abcStringEnd
1315 // can cause dynamicizeStrings to make poor decisions. So clean up before throwing.
1316 pool->_abcStringStart = NULL__null;
1317 pool->_abcStringEnd = NULL__null;
1318 VMPI_memset::memset(pool->_abcStrings->data, 0, string_count*sizeof(ConstantStringData*));
1319 toplevel->throwVerifyError(kCorruptABCError);
1320 }
1321
1322#ifdef AVMPLUS_VERBOSE
1323 if(pool->isVerbose(VB_parse)) {
1324 core->console << " " << offset << ":" << "cpool_string["<<i<<"]="
1325 << constantNames[CONSTANT_Utf8] << " ";
1326 core->console.writeN( (const char*)pos, len);
1327 core->console << "\n";
1328 }
1329#endif
1330 // skip the UTF-8 string
1331 pos += len;
1332 }
1333 pool->_abcStringEnd = pos;
1334
1335 uint32_t ns_count = readU30(pos);
1336 if (ns_count > (uint32_t)(abcEnd - pos))
1337 toplevel->throwVerifyError(kCorruptABCError);
1338
1339 RCList<Namespace> &cpool_ns = pool->cpool_ns;
1340
1341 MMGC_MEM_TYPE(pool);
1342 cpool_ns.ensureCapacity(ns_count);
1343 pool->constantNsCount = ns_count;
1344
1345#ifdef AVMPLUS_VERBOSE
1346 startpos = pos;
1347#endif
1348 for( uint32_t i = 1; i < ns_count; ++i )
1349 {
1350#ifdef AVMPLUS_VERBOSE
1351 int offset = (int)(pos-startpos);
1352#endif
1353 CHECK_POS(pos)do { if ((pos) < abcStart || (pos) >= abcEnd ) toplevel
->throwVerifyError(kCorruptABCError); } while (0)
;
1354 CPoolKind kind = (CPoolKind) *(pos++);
1355 switch(kind)
1356 {
1357 case CONSTANT_Namespace:
1358 case CONSTANT_PackageNamespace:
1359 case CONSTANT_PackageInternalNs:
1360 case CONSTANT_ProtectedNamespace:
1361 case CONSTANT_ExplicitNamespace:
1362 case CONSTANT_StaticProtectedNs:
1363 {
1364 uint32_t index = readU30(pos);
1365 Namespace::NamespaceType type = Namespace::NS_Public;
1366 switch(kind)
1367 {
1368 case CONSTANT_PackageInternalNs:
1369 type = Namespace::NS_PackageInternal;
1370 break;
1371 case CONSTANT_ProtectedNamespace:
1372 type = Namespace::NS_Protected;
1373 break;
1374 case CONSTANT_ExplicitNamespace:
1375 type = Namespace::NS_Explicit;
1376 break;
1377 case CONSTANT_StaticProtectedNs:
1378 type = Namespace::NS_StaticProtected;
1379 break;
1380 }
1381
1382 if (index)
1383 {
1384 Stringp uri = resolveUtf8(index);
1385 // Default everything to kApiVersion_VM_ALLVERSIONS for now;
1386 // getBaseURIAndApiVersion() will overwrite apiVersion
1387 // if the uri has a version mark. (Note that non-builtin
1388 // ABC should never have version marks, but we call this anyway
1389 // to strip any possible mark; this is of dubious value but it's
1390 // what we've done in the past, so we'll continue to do so.)
1391 ApiVersion apiVersion = kApiVersion_VM_ALLVERSIONS;
1392 boolbool const hasVersionMark = core->getBaseURIAndApiVersion(uri, apiVersion);
1393 if (pool->isBuiltin)
1394 {
1395 // Finally, builtin public namespaces that are in the versioned-uri list,
1396 // but don't have an explicit version mark, get whisked off into the VM_INTERNAL
1397 // hidey hole.
1398 if (!hasVersionMark && type == Namespace::NS_Public && core->isVersionedURI(uri))
1399 apiVersion = kApiVersion_VM_INTERNAL;
1400
1401 }
1402 else
1403 {
1404 // If it's not builtin, it always gets the pool's apiVersion,
1405 // even if the uri has a version mark (which shouldn't happen
1406 // with standard tools, but a deliberately constructed ABC
1407 // chunk could attempt to do so in order to access otherwise
1408 // unavailable API). (But only for
1409 if (type == Namespace::NS_Public)
1410 apiVersion = pool->getApiVersion();
1411 }
1412 Namespacep ns = core->internNamespace(core->newNamespace(uri, type, apiVersion));
1413 cpool_ns.set(i, ns);
1414 }
1415 else
1416 {
1417 // issue this looks wrong. should uri be ""?
1418 Atom uri = undefinedAtom;
1419 cpool_ns.set(i, core->internNamespace(core->newNamespace(uri, type)));
1420 }
1421 break;
1422 }
1423
1424 case CONSTANT_PrivateNs:
1425 {
1426 uint32_t index = readU30(pos);
1427 Stringp uri = index ? resolveUtf8(index) : (Stringp)core->kEmptyString;
1428 Namespacep ns = Namespace::create(core->GetGC(), nullStringAtom, uri, Namespace::NS_Private, kApiVersion_VM_ALLVERSIONS);
1429 cpool_ns.set(i, ns);
1430 break;
1431 }
1432 default:
1433 {
1434 toplevel->throwVerifyError(kCpoolEntryWrongTypeError, core->toErrorString(i));
1435 }
1436 }
1437 #ifdef AVMPLUS_VERBOSE
1438 if(pool->isVerbose(VB_parse)) {
1439 core->console << " " << offset << ":" << "cpool_ns["<<i<<"]="
1440 <<constantNames[kind] << " " << cpool_ns[i] << "\n";
1441 }
1442 #endif
1443 }
1444
1445 uint32_t ns_set_count = readU30(pos);
1446 if (ns_set_count > (uint32_t)(abcEnd - pos))
1447 toplevel->throwVerifyError(kCorruptABCError);
1448
1449 GCList<NamespaceSet>& cpool_ns_set = pool->cpool_ns_set;
1450 cpool_ns_set.ensureCapacity(ns_set_count);
1451 pool->constantNsSetCount = ns_set_count;
1452
1453#ifdef AVMPLUS_VERBOSE
1454 startpos = pos;
1455#endif
1456
1457 for( uint32_t i = 1; i < ns_set_count; ++i)
1458 {
1459#ifdef AVMPLUS_VERBOSE
1460 int offset = (int)(pos-startpos);
1461#endif
1462 uint32_t ns_count = readU30(pos);
1463
1464 if (ns_count > (uint32_t)(abcEnd - pos))
1465 toplevel->throwVerifyError(kCorruptABCError);
1466
1467 NamespaceSet* namespace_set = NamespaceSet::_create(core->GetGC(), ns_count);
1468 for(uint32_t j=0; j < ns_count; ++j)
1469 {
1470 Namespacep ns = parseNsRef(pos);
1471 if (!ns)
1472 toplevel->throwVerifyError(kIllegalNamespaceError);
1473 namespace_set->_initNsAt(j, ns);
1474 }
1475 cpool_ns_set.set(i, namespace_set);
1476
1477 #ifdef AVMPLUS_VERBOSE
1478 if(pool->isVerbose(VB_parse)) {
1479 core->console << " " << offset << ":" << "cpool_ns_set["<<i<<"]="
1480 << constantNames[CONSTANT_NamespaceSet] << " " << cpool_ns_set[i] << "\n";
1481 }
1482 #endif
1483 }
1484
1485 uint32_t mn_count = readU30(pos);
1486 if (mn_count > (uint32_t)(abcEnd - pos))
1487 toplevel->throwVerifyError(kCorruptABCError);
1488
1489 DataList<uint32_t>& cpool_mn_offsets = pool->cpool_mn_offsets;
1490
1491 MMGC_MEM_TYPE(pool);
1492 cpool_mn_offsets.ensureCapacity(mn_count);
1493
1494 for(uint32_t i = 1; i < mn_count; ++i )
1495 {
1496 CHECK_POS(pos)do { if ((pos) < abcStart || (pos) >= abcEnd ) toplevel
->throwVerifyError(kCorruptABCError); } while (0)
;
1497 uint32_t const offset = uint32_t(pos - pool->_abcStart);
1498 cpool_mn_offsets.set(i, offset);
1499 CPoolKind kind = (CPoolKind)*pos++;
1500 switch(kind)
1501 {
1502 case CONSTANT_Qname:
1503 case CONSTANT_QnameA:
1504 {
1505 // U16 namespace_index
1506 // U16 name_index
1507 // parse a multiname with one namespace (aka qname)
1508 parseNsRef(pos);
1509 parseName(pos);
1510 break;
1511 }
1512
1513 case CONSTANT_RTQname:
1514 case CONSTANT_RTQnameA:
1515 {
1516 // U16 name_index
1517 // parse a multiname with just a name; ns fetched at runtime
1518 parseName(pos);
1519 break;
1520 }
1521 case CONSTANT_RTQnameL:
1522 case CONSTANT_RTQnameLA:
1523 {
1524 break;
1525 }
1526
1527 case CONSTANT_Multiname:
1528 case CONSTANT_MultinameA:
1529 {
1530 parseName(pos);
1531
1532 uint32_t index = readU30(pos);
1533
1534 if (!index || index >= pool->constantNsSetCount)
1535 toplevel->throwVerifyError(kCpoolIndexRangeError, core->toErrorString(index), core->toErrorString(pool->constantNsSetCount));
1536
1537 // If it is in the range of Namespace Sets then it must be a namespace set/
1538 break;
1539 }
1540
1541 case CONSTANT_MultinameL:
1542 case CONSTANT_MultinameLA:
1543 {
1544 uint32_t index = readU30(pos);
1545
1546 if (!index || index >= pool->constantNsSetCount)
1547 toplevel->throwVerifyError(kCpoolIndexRangeError, core->toErrorString(index), core->toErrorString(pool->constantNsSetCount));
1548
1549 // If it is in the range of Namespace Sets then it must be a namespace set.
1550
1551 break;
1552 }
1553
1554 case CONSTANT_TypeName:
1555 {
1556 uint32_t index = readU30(pos);
1557
1558 // compare index against mn_count, *not* cpool_mn_offsets.length(), as the latter is still being built...
1559 // it's ok to forward-reference here.
1560 if(!index || index >= mn_count)
1561 toplevel->throwVerifyError(kCpoolIndexRangeError, core->toErrorString(index), core->toErrorString(mn_count));
1562
1563 index = readU30(pos);
1564 if(index != 1)
1565 toplevel->throwVerifyError(kCorruptABCError);
1566
1567 index = readU30(pos);
1568 // validate that parameterized type is valid. (note that index == 0 is
1569 // legal here, and is used for Vector<*>)
1570 if (index >= mn_count)
1571 toplevel->throwVerifyError(kCpoolIndexRangeError, core->toErrorString(index), core->toErrorString(mn_count));
1572 break;
1573 }
1574 default:
1575 toplevel->throwVerifyError(kCpoolEntryWrongTypeError, core->toErrorString(i));
1576 }
1577 #ifdef AVMPLUS_VERBOSE
1578 if(pool->isVerbose(VB_parse)) {
1579 core->console << " " << offset << ":" << "cpool_mn["<<i<<"]="
1580 <<constantNames[kind] << " ";
1581 Multiname name;
1582 pool->parseMultiname(name, i);
1583 core->console << name;
1584 core->console << "\n";
1585 }
1586 #endif
1587 }
1588
1589 {
1590 // Note that BitSet uses mmfx memory, not gc memory, so we must not
1591 // throw an exception while it's alive, lest the memory leak. Hence
1592 // the gyration with "goto corrupted" below.
1593 BitSet seen(mn_count);
1594
1595 // verify that parameterized types have no cycles.
1596 // we have to do this in a second pass since forward-references are legal
1597 for (uint32_t i = 1; i < mn_count; ++i )
1598 {
1599 const uint8_t* p = pool->_abcStart + cpool_mn_offsets[i];
1600 if (*p++ != CONSTANT_TypeName)
1601 continue;
1602
1603 uint32_t basetype_index = readU30(p); // type being parameterized (currently, always Vector)
1604
1605 // the type being parameterized can't itself be a parameterized type.
1606 // (note that this check also means cycles for this value are impossible
1607 // and need not be checked)
1608 const uint8_t* p_basetype = pool->_abcStart + cpool_mn_offsets[basetype_index];
1609 if (*p_basetype == CONSTANT_TypeName)
1610 goto corrupted; // don't throw: that would leak the BitSet
1611
1612 readU30(p); // param count (currently always 1)
1613
1614 uint32_t pt_index = readU30(p); // param type(s) (currently exactly one)
1615 // now check for cycles. we can nest arbitrarily deep (eg Vector<Vector<Vector<uint>>>)
1616 // but we can't have a cycle.
1617 seen.reset();
1618 for (;;)
1619 {
1620 if (pt_index == 0) // Vector<*> is a special case
1621 break;
1622 seen.set(pt_index);
1623 const uint8_t* p_paramtype = pool->_abcStart + cpool_mn_offsets[pt_index];
1624 if (*p_paramtype++ != CONSTANT_TypeName)
1625 break;
1626 readU30(p_paramtype); // skip type being parameterized (currently, always Vector)
1627 readU30(p_paramtype); // skip param count (currently always 1)
1628 pt_index = readU30(p_paramtype); // param type(s) (currently exactly one)
1629 if (seen.get(pt_index))
1630 goto corrupted; // don't throw: that would leak the BitSet
1631 }
1632
1633 }
1634 }
1635
1636 return;
1637
1638 corrupted:
1639 toplevel->throwVerifyError(kCorruptABCError);
1640
1641 }
1642
1643 void AbcParser::addNamedTraits(NamespaceSetp nss, Stringp name, Traits* itraits)
1644 {
1645 // check to see if the base namespace has been added, if so then
1646 // all versions have been added
1647 Namespace* ns = nss->nsAt(0);
1648 if (!ns->isPrivate()) {
1649 ApiVersion apiVersion = kApiVersion_VM_INTERNAL;
1650 for (NamespaceSetIterator iter(nss); iter.hasNext();)
1651 {
1652 Namespacep nsi = iter.next();
1653 ApiVersion a = core->getValidApiVersion(nsi->getApiVersion());
1654 if (a < apiVersion)
1655 apiVersion = a;
1656 }
1657 ns = core->getVersionedNamespace(ns, apiVersion);
1658 core->domainMgr()->addNamedTraits(pool, name, ns, itraits);
1659 }
1660 }
1661
1662 void AbcParser::addNamedTraits(Namespacep ns, Stringp name, Traits* itraits)
1663 {
1664 if (!ns->isPrivate()) {
1665 core->domainMgr()->addNamedTraits(pool, name, ns, itraits);
1666 }
1667 }
1668
1669 void AbcParser::addNamedScript(NamespaceSetp nss, Stringp name, MethodInfo* script)
1670 {
1671 Namespacep ns = nss->nsAt(0); // just need one
1672 if (!ns->isPrivate())
1673 {
1674 ApiVersion apiVersion = kApiVersion_VM_INTERNAL;
1675 for (NamespaceSetIterator iter(nss); iter.hasNext();)
1676 {
1677 Namespacep nsi = iter.next();
1678 ApiVersion a = core->getValidApiVersion(nsi->getApiVersion());
1679 if (a < apiVersion)
1680 apiVersion = a;
1681 }
1682 ns = core->getVersionedNamespace(ns, apiVersion);
1683 }
1684 core->domainMgr()->addNamedScript(pool, name, ns, script);
1685 }
1686
1687 boolbool AbcParser::parseScriptInfos()
1688 {
1689 /*
1690 U16 script_count
1691 ScriptInfo[script_count]
1692 {
1693 U16 init_index // method_info index of init function
1694 Traits script_traits // traits for the global object of this package
1695 }
1696 */
1697
1698 uint32_t count = readU30(pos);
1699
1700 #ifdef AVMPLUS_VERBOSE
1701 if(pool->isVerbose(VB_parse)) {
1702 core->console << "script_count=" << count << "\n";
1703 }
1704 #endif
1705
1706#ifdef AVMPLUS_VERBOSE
1707 const uint8_t* startpos = pos;
1708#endif
1709
1710 if (count == 0)
1711 {
1712 return truetrue;
1713 }
1714
1715 if (count > (uint32_t)(abcEnd - pos))
1716 toplevel->throwVerifyError(kCorruptABCError);
1717
1718 pool->_scripts.ensureCapacity(count);
1719
1720 // make global objects subclasses of Object
1721
1722 for (uint32_t i=0; i < count; i++)
1723 {
1724 const uint8_t* script_pos = pos;
1725
1726 int init_index = readU30(pos);
1727
1728 #ifdef AVMPLUS_VERBOSE
1729 if(pool->isVerbose(VB_parse)) {
1730 core->console << " " << (int)(script_pos-startpos) << ":script[" << i << "]"
1731 << " init_index=" << init_index
1732 << "\n";
1733 }
1734 #endif
1735 MethodInfo* script = resolveMethodInfo(init_index);
1736 Traits* declaringTraits = script->declaringTraits();
1737
1738 if (declaringTraits != NULL__null)
1739 {
1740 // method has already been bound to a different type. Can't bind it twice because
1741 // it can only have one environment, for its scope chain and super references.
1742 toplevel->throwVerifyError(kAlreadyBoundError, core->toErrorString(script), core->toErrorString(declaringTraits));
1743 }
1744
1745 Traits* traits = parseTraits(sizeof(ScriptObject),
1746 sizeof(ScriptObject),
1747 core->traits.object_itraits,
1748 core->getPublicNamespace(pool),
1749 core->kglobal,
1750 script,
1751 script_pos,
1752 TRAITSTYPE_SCRIPT,
1753 NULL__null);
1754
1755 if( !traits ) return falsefalse; // parseTraits failed
1756
1757
1758 // global object, make it dynamic
1759 traits->set_needsHashtable(truetrue);
1760
1761 script->makeMethodOf(traits);
1762 traits->init = script;
1763 script->setStaticInit();
1764
1765 pool->_scripts.set(i, traits);
1766#ifdef VMCFG_AOT
1767 pool->aotInfo->scriptTraits[i] = traits;
1768#endif
1769 }
1770
1771 return truetrue;
1772 }
1773
1774 boolbool AbcParser::parseInstanceInfos()
1775 {
1776 classCount = readU30(pos);
1777#ifdef AVMPLUS_VERBOSE
1778 if(pool->isVerbose(VB_parse)) {
1779 core->console << "class_count=" << classCount <<"\n";
1780 }
1781#endif
1782
1783#ifdef AVMPLUS_VERBOSE
1784 const uint8_t* startpos = pos;
1785#endif
1786
1787 if (classCount == 0)
1788 {
1789 return truetrue;
1790 }
1791
1792 if (classCount > uintptr_t(abcEnd - pos))
1793 toplevel->throwVerifyError(kCorruptABCError);
1794
1795 // allocate room for class infos early, to handle nested classes
1796 pool->_classes.ensureCapacity(classCount);
1797
1798 instances.ensureCapacity(classCount);
1799
1800 for (uint32_t i=0; i < classCount; i++)
1801 {
1802 const uint8_t* instancepos = pos;
1803
1804 // CONSTANT_QName name of this class
1805
1806 Multiname mn;
1807 resolveBindingName(pos, mn);
1808 Namespacep ns;
1809 Stringp name;
1810 name = mn.getName();
1811 const NamespaceSet* nss;
1812 if (mn.namespaceCount() > 1)
1813 {
1814 nss = mn.getNsset();
1815 ns = nss->nsAt(0);
1816 }
1817 else
1818 {
1819 ns = mn.getNamespace();
1820 nss = NamespaceSet::create(core->GetGC(), ns);
1821 }
1822
1823 // resolving base class type means class heirarchy must be a Tree
1824 Traits* baseTraits = pool->resolveTypeName(pos, toplevel);
1825
1826 if ((baseTraits && baseTraits->final) ||
1827 (CLASS_TYPE(core->traits.class_itraits) != NULL__null && baseTraits == CLASS_TYPE(core->traits.class_itraits)) ||
1828 // note, builtins are allowed to override Function
1829 (FUNCTION_TYPE(core->traits.function_itraits) != NULL__null && baseTraits == FUNCTION_TYPE(core->traits.function_itraits) && !pool->isBuiltin))
1830 {
1831 // error - attempt to extend final class
1832 #ifdef AVMPLUS_VERBOSE
1833 if(pool->isVerbose(VB_parse)) {
1834 core->console << mn << " can't extend final class " << baseTraits << "\n";
1835 }
1836 #endif
1837 toplevel->throwVerifyError(kCannotExtendFinalClass, core->toErrorString(&mn));
1838 }
1839
1840 if (baseTraits && baseTraits->isInterface())
1841 {
1842 // error, can't extend interface
1843 toplevel->throwVerifyError(kCannotExtendError, core->toErrorString(&mn), core->toErrorString(baseTraits));
1844 }
1845
1846 // read flags: bit 0: sealed
1847 // bit 1: final
1848 // bit 2: interface
1849 // bit 3: protected
1850 CHECK_POS(pos)do { if ((pos) < abcStart || (pos) >= abcEnd ) toplevel
->throwVerifyError(kCorruptABCError); } while (0)
;
1851 int flags = *pos++;
1852
1853 // read protected namespace
1854 Namespacep protectedNamespace = NULL__null;
1855 if (flags & 8)
1856 {
1857 protectedNamespace = parseNsRef(pos);
1858 }
1859
1860 int interfaceCount = readU30(pos);
1861 const uint8_t* interfacePos = pos;
1862
1863 if(interfaceCount)
1864 {
1865 if (interfaceCount >= 0x10000000)
1866 toplevel->throwVerifyError(kCorruptABCError);
1867
1868 for( int x = 0; x < interfaceCount; ++ x )
1869 {
1870 Traits *t = pool->resolveTypeName(pos, toplevel);
1871 if (!t || !t->isInterface())
1872 {
1873 // error, can't implement non-interface type
1874 toplevel->throwVerifyError(kCannotImplementError, core->toErrorString(&mn), core->toErrorString(t));
1875 }
1876 }
1877 }
1878
1879 // TODO make sure the inheritance is legal.
1880 // - can't override final members
1881 // - overrides agree with base class signature
1882
1883 uint32_t iinit_index = readU30(pos);
1884 MethodInfo* iinit = resolveMethodInfo(iinit_index);
1885
1886#ifdef AVMPLUS_VERBOSE
1887 if(pool->isVerbose(VB_parse)) {
1888 // TODO: fixup this math here, since the 2's are all wrong
1889 core->console
1890 << " " << (int)(instancepos-startpos) << ":instance[" << i << "]"
1891 << " " << mn;
1892
1893 if (baseTraits)
1894 core->console << " extends " << baseTraits;
1895
1896 core->console
1897 << " interface_count=" << interfaceCount
1898 << " iinit_index=" << iinit_index
1899 << "\n";
1900 }
1901#endif
1902 TraitsPosType postype = (flags & 4) ? TRAITSTYPE_INTERFACE : TRAITSTYPE_INSTANCE;
1903 uint16_t sizeofInstance, offsetofSlots;
1904
1905 // If this is a native class, use the stated instance size and offset to slot area.
1906 const NativeClassInfo* nativeEntry;
1907 if (natives && (nativeEntry = natives->get_class(i)) != NULL__null && nativeEntry->sizeofInstance)
1908 {
1909 sizeofInstance = nativeEntry->sizeofInstance;
1910 offsetofSlots = nativeEntry->offsetofSlotsInstance;
1911 // note that 0 means "put the slots at the end of my immediate parent",
1912 // but don't assert here: builtin classes without any slots (e.g., Object)
1913 // emit a 0 here for simplicity. Since we won't be generating any slot
1914 // offsets for the class anyway, it doesn't matter...
1915 // AvmAssert(offsetofSlots > 0);
1916 }
1917 else
1918 {
1919 // Since nativegen.py emits "synthetic" C++ classes for all builtin classes (except interfaces),
1920 // only non-builtin classes should hit this code; since they don't have C++ representations,
1921 // "overlap" of fields between parent and child isn't possibly so we can safely declare the
1922 // offsetOfSlots to be an the end of the base.
1923#ifdef VMCFG_VERIFYALL
1924 // (Don't bother with this assert in verifyonly mode, as avmglue.abc (etc) will appear to be
1925 // non-builtin (since we specify them as arguments, triggering false positives)
1926 if (!core->config.verifyonly)
1927#endif
1928 {
1929 AvmAssert(postype == TRAITSTYPE_INTERFACE || !pool->isBuiltin)do { } while (0);
1930 }
1931
1932 // 0 means "put the slots at the end of my immediate parent"
1933 offsetofSlots = 0;
1934 // Assume ScriptObject for now
1935 sizeofInstance = uint16_t(sizeof(ScriptObject));
1936 // Search the inheritance chain for any native classes.
1937 for (Traits* b = baseTraits; b != NULL__null; b = b->base)
1938 {
1939 if (b->getSizeOfInstance() > sizeof(ScriptObject))
1940 {
1941 // non-Object base class uses a subclass of ScriptObject, so use that size.
1942 sizeofInstance = b->getSizeOfInstance();
1943 break;
1944 }
1945 }
1946 }
1947
1948 Traits* itraits = parseTraits(sizeofInstance,
1949 offsetofSlots,
1950 baseTraits,
1951 ns,
1952 name,
1953 0,
1954 instancepos,
1955 postype,
1956 protectedNamespace,
1957 (flags&2) != 0);
1958 if( !itraits ) return falsefalse;
1959 if (!baseTraits && core->traits.object_itraits == NULL__null)
1960 {
1961 // save object traits
1962 core->traits.object_itraits = itraits;
1963 itraits->builtinType = BUILTIN_object;
1964 }
1965
1966 // AS3 language decision: dynamic is not inherited.
1967 itraits->set_needsHashtable((flags&1) == 0);
1968
1969 if (itraits->isInterface())
1970 {
1971 // check for slotCount != 0 now done at resolve time
1972
1973 // interface base must be *
1974 if (baseTraits)
1975 {
1976 // error, can't extend this type
1977 toplevel->throwVerifyError(kCannotExtendError, core->toErrorString(&mn), core->toErrorString(baseTraits));
1978 }
1979 }
1980
1981 Traits* declaringTraits = iinit->declaringTraits();
1982 if (declaringTraits != NULL__null)
1983 {
1984 // method has already been bound to a different type. Can't bind it twice because
1985 // it can only have one environment, for its scope chain and super references.
1986 toplevel->throwVerifyError(kAlreadyBoundError, core->toErrorString(iinit), core->toErrorString(declaringTraits));
1987 }
1988
1989 iinit->makeMethodOf(itraits);
1990 itraits->init = iinit;
1991
1992#ifdef AVMPLUS_VERBOSE
1993 // print the interfaces. interfaces have been resolved above so any
1994 // errors would have been reported earlier.
1995 for (int j=0, n=interfaceCount; j < n; j++)
1996 {
1997 Traits *interfaceTraits = pool->resolveTypeName(interfacePos, toplevel);
1998 if(pool->isVerbose(VB_parse)) {
1999 core->console << " interface["<<j<<"]=" << interfaceTraits <<"\n";
2000 }
2001 }
2002#else
2003 (void)interfacePos;
2004#endif
2005
2006 instances.set(i, itraits);
2007
2008 core->domainMgr()->addNamedInstanceTraits(pool, name, ns, itraits);
2009 }
2010
2011 return truetrue;
2012 }
2013
2014 void AbcParser::parseClassInfos()
2015 {
2016 if (classCount == 0)
2017 {
2018 return;
2019 }
2020
2021#ifdef AVMPLUS_VERBOSE
2022 const uint8_t* startpos = pos;
2023#endif
2024
2025 for (uint32_t i=0; i < classCount; i++)
2026 {
2027 // CONSTANT_Multiname name of this class
2028 Traits* itraits = instances[i];
2029 Namespacep ns = itraits->ns();
2030 Stringp name = itraits->name();
2031
2032 const uint8_t* class_pos = pos;
2033
2034 uint32_t cinit_index = readU30(pos);
2035 MethodInfo* cinit = resolveMethodInfo(cinit_index);
2036
2037 #ifdef AVMPLUS_VERBOSE
2038 if(pool->isVerbose(VB_parse)) {
2039 core->console
2040 << " " << (int)(class_pos-startpos) << ":class[" << i << "]"
2041 << " " << ns << "::" << name;
2042
2043 core->console
2044 << " cinit_index=" << cinit_index
2045 << "\n";
2046 }
2047 #endif
2048
2049 const NativeClassInfo* nativeEntry = natives ? natives->get_class(i) : NULL__null;
2050 boolbool haveClassNativeInfo = nativeEntry && nativeEntry->sizeofClass;
2051 Traits* ctraits = parseTraits(haveClassNativeInfo ? nativeEntry->sizeofClass : sizeof(ClassClosure),
2052 haveClassNativeInfo ? nativeEntry->offsetofSlotsClass : sizeof(ClassClosure),
2053 CLASS_TYPE(core->traits.class_itraits),
2054 ns,
2055 core->internString(core->concatStrings(name, core->newConstantStringLatin1("$"))),
2056 NULL__null,
2057 class_pos,
2058 TRAITSTYPE_CLASS,
2059 itraits->protectedNamespace);
2060 if (haveClassNativeInfo)
2061 {
2062 ctraits->hasCustomConstruct = nativeEntry->hasCustomConstruct;
2063 itraits->isRestrictedInheritance = nativeEntry->isRestrictedInheritance;
2064 itraits->isAbstractBase = nativeEntry->isAbstractBase;
2065 }
2066 ctraits->setCreateClassClosureProc(haveClassNativeInfo ? nativeEntry->createClassClosure : ClassClosure::createClassClosure);
2067
2068 Traits* declaringTraits = cinit->declaringTraits();
2069 if (declaringTraits != NULL__null)
2070 {
2071 // method has already been bound to a different type. Can't bind it twice because
2072 // it can only have one environment, for its scope chain and super references.
2073 toplevel->throwVerifyError(kAlreadyBoundError, core->toErrorString(cinit), core->toErrorString(declaringTraits));
2074 }
2075
2076 cinit->makeMethodOf(ctraits);
2077 ctraits->init = cinit;
2078 ctraits->itraits = itraits;
2079 ctraits->set_needsHashtable(truetrue);
2080 cinit->setStaticInit();
2081
2082 pool->_classes.set(i, ctraits);
2083 }
2084 }
2085
2086 uint32_t AbcParser::readU30(const uint8_t*& p) const
2087 {
2088 // We have added kBufferPadding bytes to the end of the main swf buffer.
2089 // Why? Here we can read from 1 to 5 bytes. If we were to
2090 // put the required safety checks at each uint8_t read, we would slow
2091 // parsing of the file down. With this buffer, only one check at the
2092 // top of this function is necessary. (we will read on into our own memory)
2093 CHECK_POS(p)do { if ((p) < abcStart || (p) >= abcEnd ) toplevel->
throwVerifyError(kCorruptABCError); } while (0)
;
2094 return toplevel->readU30(p);
2095 }
2096
2097 double AbcParser::readDouble(const uint8_t* &p) const
2098 {
2099 // check to see if we are trying to read past the file end.
2100 if (p < abcStart || p+7 >= abcEnd )
2101 toplevel->throwVerifyError(kCorruptABCError);
2102
2103 double_overlay d;
2104 d.words.lsw = p[0] | p[1]<<8 | p[2]<<16 | p[3]<<24;
2105 d.words.msw = p[4] | p[5]<<8 | p[6]<<16 | p[7]<<24;
2106 p += 8;
2107 return d.value;
2108 }
2109}