summaryrefslogtreecommitdiff
path: root/libxerces-c/xercesc/dtd-decl-use-after-free.patch
blob: ad13ca0aac4f7a42ae82decf61e80cda625dda1d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
diff --git a/libxerces-c/xercesc/internal/DGXMLScanner.cpp b/libxerces-c/xercesc/internal/DGXMLScanner.cpp
index 4334223..895dfeb 100644
--- a/libxerces-c/xercesc/internal/DGXMLScanner.cpp
+++ b/libxerces-c/xercesc/internal/DGXMLScanner.cpp
@@ -1052,13 +1052,12 @@ void DGXMLScanner::scanDocTypeDecl()
             DTDEntityDecl* declDTD = new (fMemoryManager) DTDEntityDecl(gDTDStr, false, fMemoryManager);
             declDTD->setSystemId(sysId);
             declDTD->setIsExternal(true);
-            Janitor<DTDEntityDecl> janDecl(declDTD);
 
             // Mark this one as a throw at end
             reader->setThrowAtEnd(true);
 
             // And push it onto the stack, with its pseudo name
-            fReaderMgr.pushReader(reader, declDTD);
+            fReaderMgr.pushReaderAdoptEntity(reader, declDTD);
 
             // Tell it its not in an include section
             dtdScanner.scanExtSubsetDecl(false, true);
@@ -2131,13 +2130,12 @@ Grammar* DGXMLScanner::loadDTDGrammar(const InputSource& src,
     DTDEntityDecl* declDTD = new (fMemoryManager) DTDEntityDecl(gDTDStr, false, fMemoryManager);
     declDTD->setSystemId(src.getSystemId());
     declDTD->setIsExternal(true);
-    Janitor<DTDEntityDecl> janDecl(declDTD);
 
     // Mark this one as a throw at end
     newReader->setThrowAtEnd(true);
 
     // And push it onto the stack, with its pseudo name
-    fReaderMgr.pushReader(newReader, declDTD);
+    fReaderMgr.pushReaderAdoptEntity(newReader, declDTD);
 
     //  If we have a doc type handler and advanced callbacks are enabled,
     //  call the doctype event.
diff --git a/libxerces-c/xercesc/internal/IGXMLScanner.cpp b/libxerces-c/xercesc/internal/IGXMLScanner.cpp
index 912ec0c..d694b23 100644
--- a/libxerces-c/xercesc/internal/IGXMLScanner.cpp
+++ b/libxerces-c/xercesc/internal/IGXMLScanner.cpp
@@ -1535,13 +1535,12 @@ void IGXMLScanner::scanDocTypeDecl()
             DTDEntityDecl* declDTD = new (fMemoryManager) DTDEntityDecl(gDTDStr, false, fMemoryManager);
             declDTD->setSystemId(sysId);
             declDTD->setIsExternal(true);
-            Janitor<DTDEntityDecl> janDecl(declDTD);
 
             // Mark this one as a throw at end
             reader->setThrowAtEnd(true);
 
             // And push it onto the stack, with its pseudo name
-            fReaderMgr.pushReader(reader, declDTD);
+            fReaderMgr.pushReaderAdoptEntity(reader, declDTD);
 
             // Tell it its not in an include section
             dtdScanner.scanExtSubsetDecl(false, true);
@@ -3098,13 +3097,12 @@ Grammar* IGXMLScanner::loadDTDGrammar(const InputSource& src,
     DTDEntityDecl* declDTD = new (fMemoryManager) DTDEntityDecl(gDTDStr, false, fMemoryManager);
     declDTD->setSystemId(src.getSystemId());
     declDTD->setIsExternal(true);
-    Janitor<DTDEntityDecl> janDecl(declDTD);
 
     // Mark this one as a throw at end
     newReader->setThrowAtEnd(true);
 
     // And push it onto the stack, with its pseudo name
-    fReaderMgr.pushReader(newReader, declDTD);
+    fReaderMgr.pushReaderAdoptEntity(newReader, declDTD);
 
     //  If we have a doc type handler and advanced callbacks are enabled,
     //  call the doctype event.
diff --git a/libxerces-c/xercesc/internal/ReaderMgr.cpp b/libxerces-c/xercesc/internal/ReaderMgr.cpp
index d14483e..369a1ba 100644
--- a/libxerces-c/xercesc/internal/ReaderMgr.cpp
+++ b/libxerces-c/xercesc/internal/ReaderMgr.cpp
@@ -45,12 +45,61 @@
 
 XERCES_CPP_NAMESPACE_BEGIN
 
+// ---------------------------------------------------------------------------
+//  ReaderMgr::ReaderData: Constructors and Destructor
+// ---------------------------------------------------------------------------
+ReaderMgr::ReaderData::ReaderData( XMLReader* const       reader
+                                   , XMLEntityDecl* const entity
+                                   , const bool           adoptEntity) :
+
+    fReader(reader)
+    , fEntity(entity)
+    , fEntityAdopted(adoptEntity)
+{
+}
+
+ReaderMgr::ReaderData::~ReaderData()
+{
+    delete fReader;
+
+    if (fEntityAdopted)
+        delete fEntity;
+}
+
+// ---------------------------------------------------------------------------
+//  ReaderMgr::ReaderData: Getter methods
+// ---------------------------------------------------------------------------
+XMLReader* ReaderMgr::ReaderData::getReader() const
+{
+  return fReader;
+}
+
+XMLEntityDecl* ReaderMgr::ReaderData::getEntity() const
+{
+  return fEntity;
+}
+
+bool ReaderMgr::ReaderData::getEntityAdopted() const
+{
+  return fEntityAdopted;
+}
+
+//
+//  This method gives up the entity object ownership but leaves the fEntity
+//  pointer intact.
+//
+XMLEntityDecl* ReaderMgr::ReaderData::releaseEntity()
+{
+  fEntityAdopted = false;
+  return fEntity;
+}
+
 // ---------------------------------------------------------------------------
 //  ReaderMgr: Constructors and Destructor
 // ---------------------------------------------------------------------------
 ReaderMgr::ReaderMgr(MemoryManager* const manager) :
 
-    fCurEntity(0)
+    fCurReaderData(0)
     , fCurReader(0)
     , fEntityHandler(0)
     , fEntityStack(0)
@@ -66,12 +115,11 @@ ReaderMgr::ReaderMgr(MemoryManager* const manager) :
 ReaderMgr::~ReaderMgr()
 {
     //
-    //  Clean up the reader and entity stacks. Note that we don't own the
-    //  entities, so we don't delete the current entity (and the entity stack
-    //  does not own its elements either, so deleting it will not delete the
-    //  entities it still references!)
+    //  Clean up the reader stack and orphan entities container. Note that
+    //  all adopted entities (potentially contained in fCurReaderData,
+    //  fReaderStack, and fEntityStack) are deleted here.
     //
-    delete fCurReader;
+    delete fCurReaderData;
     delete fReaderStack;
     delete fEntityStack;
 }
@@ -357,9 +405,9 @@ void ReaderMgr::cleanStackBackTo(const XMLSize_t readerNum)
         if (fReaderStack->empty())
             ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::RdrMgr_ReaderIdNotFound, fMemoryManager);
 
-        delete fCurReader;
-        fCurReader = fReaderStack->pop();
-        fCurEntity = fEntityStack->pop();
+        delete fCurReaderData;
+        fCurReaderData = fReaderStack->pop();
+        fCurReader = fCurReaderData->getReader ();
     }
 }
 
@@ -795,20 +843,20 @@ const XMLCh* ReaderMgr::getCurrentEncodingStr() const
 
 const XMLEntityDecl* ReaderMgr::getCurrentEntity() const
 {
-    return fCurEntity;
+    return fCurReaderData? fCurReaderData->getEntity() : 0;
 }
 
 
 XMLEntityDecl* ReaderMgr::getCurrentEntity()
 {
-    return fCurEntity;
+    return fCurReaderData? fCurReaderData->getEntity() : 0;
 }
 
 
 XMLSize_t ReaderMgr::getReaderDepth() const
 {
     // If the stack doesn't exist, its obviously zero
-    if (!fEntityStack)
+    if (!fReaderStack)
         return 0;
 
     //
@@ -816,7 +864,7 @@ XMLSize_t ReaderMgr::getReaderDepth() const
     //  reader. So if there is no current reader and none on the stack,
     //  its zero, else its some non-zero value.
     //
-    XMLSize_t retVal = fEntityStack->size();
+    XMLSize_t retVal = fReaderStack->size();
     if (fCurReader)
         retVal++;
     return retVal;
@@ -852,7 +900,7 @@ void ReaderMgr::getLastExtEntityInfo(LastExtEntityInfo& lastInfo) const
 bool ReaderMgr::isScanningPERefOutOfLiteral() const
 {
     // If the current reader is not for an entity, then definitely not
-    if (!fCurEntity)
+    if (!fCurReaderData || !fCurReaderData->getEntity())
         return false;
 
     //
@@ -867,13 +915,19 @@ bool ReaderMgr::isScanningPERefOutOfLiteral() const
     return false;
 }
 
-
 bool ReaderMgr::pushReader(         XMLReader* const        reader
                             ,       XMLEntityDecl* const    entity)
+{
+    return pushReaderAdoptEntity(reader, entity, false);
+}
+
+bool ReaderMgr::pushReaderAdoptEntity(     XMLReader* const        reader
+                                       ,   XMLEntityDecl* const    entity
+                                       ,   const bool              adoptEntity)
 {
     //
     //  First, if an entity was passed, we have to confirm that this entity
-    //  is not already on the entity stack. If so, then this is a recursive
+    //  is not already on the reader stack. If so, then this is a recursive
     //  entity expansion, so we issue an error and refuse to put the reader
     //  on the stack.
     //
@@ -881,19 +935,30 @@ bool ReaderMgr::pushReader(         XMLReader* const        reader
     //  nothing to do. If there is no entity stack yet, then of coures it
     //  cannot already be there.
     //
-    if (entity && fEntityStack)
+    if (entity && fReaderStack)
     {
-        const XMLSize_t count = fEntityStack->size();
+        // @@ Strangely, we don't check the entity at the top of the stack
+        //    (fCurReaderData). Is it a bug?
+        //
+        const XMLSize_t count = fReaderStack->size();
         const XMLCh* const theName = entity->getName();
         for (XMLSize_t index = 0; index < count; index++)
         {
-            const XMLEntityDecl* curDecl = fEntityStack->elementAt(index);
+            const XMLEntityDecl* curDecl =
+              fReaderStack->elementAt(index)->getEntity();
+
             if (curDecl)
             {
                 if (XMLString::equals(theName, curDecl->getName()))
                 {
-                    // Oops, already there so delete reader and return
+                    // Oops, already there so delete reader and entity and
+                    // return.
+                    //
                     delete reader;
+
+                    if (adoptEntity)
+                      delete entity;
+
                     return false;
                 }
             }
@@ -905,52 +970,37 @@ bool ReaderMgr::pushReader(         XMLReader* const        reader
     //  tell it it does own its elements.
     //
     if (!fReaderStack)
-        fReaderStack = new (fMemoryManager) RefStackOf<XMLReader>(16, true, fMemoryManager);
-
-    // And the entity stack, which does not own its elements
-    if (!fEntityStack)
-        fEntityStack = new (fMemoryManager) RefStackOf<XMLEntityDecl>(16, false, fMemoryManager);
+        fReaderStack = new (fMemoryManager) RefStackOf<ReaderData>(16, true, fMemoryManager);
 
     //
-    //  Push the current reader and entity onto their respective stacks.
-    //  Note that the the current entity can be null if the current reader
-    //  is not for an entity.
+    //  Push the current reader and entity onto the stack. Note that
+    //  the current entity can be null if the current reader is not for
+    //  an entity.
     //
-    if (fCurReader)
-    {
-        fReaderStack->push(fCurReader);
-        fEntityStack->push(fCurEntity);
-    }
+    if (fCurReaderData)
+        fReaderStack->push(fCurReaderData);
 
     //
     //  Make the passed reader and entity the current top of stack. The
     //  passed entity can (and often is) null.
     //
+    fCurReaderData = new (fMemoryManager) ReaderData(reader, entity, adoptEntity);
     fCurReader = reader;
-    fCurEntity = entity;
 
     return true;
 }
 
-
 void ReaderMgr::reset()
 {
     // Reset all of the flags
     fThrowEOE = false;
 
     // Delete the current reader and flush the reader stack
-    delete fCurReader;
+    delete fCurReaderData;
+    fCurReaderData = 0;
     fCurReader = 0;
     if (fReaderStack)
         fReaderStack->removeAllElements();
-
-    //
-    //  And do the same for the entity stack, but don't delete the current
-    //  entity (if any) since we don't own them.
-    //
-    fCurEntity = 0;
-    if (fEntityStack)
-        fEntityStack->removeAllElements();
 }
 
 
@@ -1014,7 +1064,9 @@ ReaderMgr::getLastExtEntity(const XMLEntityDecl*& itsEntity) const
     //  search the stack; else, keep the reader that we've got since its
     //  either an external entity reader or the main file reader.
     //
-    const XMLEntityDecl* curEntity = fCurEntity;
+    const XMLEntityDecl* curEntity =
+      fCurReaderData? fCurReaderData->getEntity() : 0;
+
     if (curEntity && !curEntity->isExternal())
     {
         XMLSize_t index = fReaderStack->size();
@@ -1024,7 +1076,7 @@ ReaderMgr::getLastExtEntity(const XMLEntityDecl*& itsEntity) const
             {
                 // Move down to the previous element and get a pointer to it
                 index--;
-                curEntity = fEntityStack->elementAt(index);
+                curEntity = fReaderStack->elementAt(index)->getEntity();
 
                 //
                 //  If its null or its an external entity, then this reader
@@ -1032,12 +1084,12 @@ ReaderMgr::getLastExtEntity(const XMLEntityDecl*& itsEntity) const
                 //
                 if (!curEntity)
                 {
-                    theReader = fReaderStack->elementAt(index);
+                    theReader = fReaderStack->elementAt(index)->getReader ();
                     break;
                 }
                  else if (curEntity->isExternal())
                 {
-                    theReader = fReaderStack->elementAt(index);
+                    theReader = fReaderStack->elementAt(index)->getReader ();
                     break;
                 }
 
@@ -1048,6 +1100,11 @@ ReaderMgr::getLastExtEntity(const XMLEntityDecl*& itsEntity) const
         }
     }
 
+    // @@ It feels like we may end up with theReader being from the top of
+    //    the stack (fCurReader) and itsEntity being from the bottom of the
+    //    stack (if there are no null or external entities on the stack).
+    //    Is it a bug?
+    //
     itsEntity = curEntity;
     return theReader;
 }
@@ -1059,31 +1116,59 @@ bool ReaderMgr::popReader()
     //  We didn't get any more, so try to pop off a reader. If the reader
     //  stack is empty, then we are at the end, so return false.
     //
+    //  @@ It feels like we never pop the reader pushed to the stack first
+    //     (think of fReaderStack empty but fCurReader not null). Is it a
+    //     bug?
+    //
     if (fReaderStack->empty())
         return false;
 
     //
-    //  Remember the current entity, before we pop off a new one. We might
+    //  Remember the current reader, before we pop off a new one. We might
     //  need this to throw the end of entity exception at the end.
     //
-    XMLEntityDecl* prevEntity = fCurEntity;
+    ReaderData* prevReaderData = fCurReaderData;
     const bool prevReaderThrowAtEnd = fCurReader->getThrowAtEnd();
     const XMLSize_t readerNum = fCurReader->getReaderNum();
 
     //
-    //  Delete the current reader and pop a new reader and entity off
-    //  the stacks.
+    //  Pop a new reader and entity off the stack.
     //
-    delete fCurReader;
-    fCurReader = fReaderStack->pop();
-    fCurEntity = fEntityStack->pop();
+    fCurReaderData = fReaderStack->pop();
+    fCurReader = fCurReaderData->getReader();
 
     //
     //  If there was a previous entity, and either the fThrowEOE flag is set
-    //  or reader was marked as such, then throw an end of entity.
+    //  or reader was marked as such, then throw an end of entity. Otherwise,
+    //  delete the previous reader data.
     //
-    if (prevEntity && (fThrowEOE || prevReaderThrowAtEnd))
-        throw EndOfEntityException(prevEntity, readerNum);
+    if (prevReaderData->getEntity() && (fThrowEOE || prevReaderThrowAtEnd))
+    {
+        //
+        // If the entity is adopted, then move it to fEntityStack so that
+        // its life-time is prolonged to the life-time of this reader
+        // manager. Also delete the previous reader data before throwing
+        // EndOfEntityException.
+        //
+        XMLEntityDecl* entity;
+
+        if (prevReaderData->getEntityAdopted())
+        {
+            if (!fEntityStack)
+                fEntityStack = new (fMemoryManager) RefStackOf<XMLEntityDecl>(16, true, fMemoryManager);
+
+            entity = prevReaderData->releaseEntity();
+            fEntityStack->push(entity);
+        }
+        else
+            entity = prevReaderData->getEntity();
+
+        delete prevReaderData;
+
+        throw EndOfEntityException(entity, readerNum);
+    }
+    else
+        delete prevReaderData;
 
     while (true)
     {
@@ -1113,9 +1198,9 @@ bool ReaderMgr::popReader()
             return false;
 
         // Else pop again and try it one more time
-        delete fCurReader;
-        fCurReader = fReaderStack->pop();
-        fCurEntity = fEntityStack->pop();
+        delete fCurReaderData;
+        fCurReaderData = fReaderStack->pop();
+        fCurReader = fCurReaderData->getReader();
     }
     return true;
 }
diff --git a/libxerces-c/xercesc/internal/ReaderMgr.hpp b/libxerces-c/xercesc/internal/ReaderMgr.hpp
index f63b219..3209564 100644
--- a/libxerces-c/xercesc/internal/ReaderMgr.hpp
+++ b/libxerces-c/xercesc/internal/ReaderMgr.hpp
@@ -160,6 +160,12 @@ public :
                 XMLReader* const        reader
         ,       XMLEntityDecl* const    entity
     );
+    bool pushReaderAdoptEntity
+    (
+                XMLReader* const        reader
+        ,       XMLEntityDecl* const    entity
+        ,       const bool              adoptEntity = true
+    );
     void reset();
 
 
@@ -208,16 +214,72 @@ private :
     ReaderMgr(const ReaderMgr&);
     ReaderMgr& operator=(const ReaderMgr&);
 
+    // -----------------------------------------------------------------------
+    //  Private data types
+    // -----------------------------------------------------------------------
+    class ReaderData : public XMemory
+    {
+    public  :
+      // ---------------------------------------------------------------------
+      //  Constructors and Destructor
+      // ---------------------------------------------------------------------
+      ReaderData
+      (    XMLReader* const     reader
+         , XMLEntityDecl* const entity
+         , const bool           adoptEntity
+      );
+
+      ~ReaderData();
+
+      // ----------------------------------------------------------------------
+      //  Getter methods
+      // ----------------------------------------------------------------------
+      XMLReader* getReader() const;
+      XMLEntityDecl* getEntity() const;
+      bool getEntityAdopted() const;
+
+      XMLEntityDecl* releaseEntity();
+
+    private :
+      // ---------------------------------------------------------------------
+      //  Unimplemented constructors and operators
+      // ---------------------------------------------------------------------
+      ReaderData();
+      ReaderData(const ReaderData&);
+      ReaderData& operator=(const ReaderData&);
+
+      // ---------------------------------------------------------------------
+      //  Private data members
+      //
+      //  fReader
+      //      This is the pointer to the reader object that must be destroyed
+      //      when this object is destroyed.
+      //
+      //  fEntity
+      //  fEntityAdopted
+      //      This is the pointer to the entity object that, if adopted, must
+      //      be destroyed when this object is destroyed.
+      //
+      //      Note that we need to keep up with which of the pushed readers
+      //      are pushed entity values that are being spooled. This is done
+      //      to avoid the problem of recursive definitions.
+      // ---------------------------------------------------------------------
+      XMLReader*     fReader;
+      XMLEntityDecl* fEntity;
+      bool           fEntityAdopted;
+    };
+
     // -----------------------------------------------------------------------
     //  Private data members
     //
-    //  fCurEntity
-    //      This is the current top of stack entity. We pull it off the stack
-    //      and store it here for efficiency.
+    //  fCurReaderData
+    //      This is the current top of the reader data stack. We pull it off
+    //      the stack and store it here for efficiency.
     //
     //  fCurReader
-    //      This is the current top of stack reader. We pull it off the
-    //      stack and store it here for efficiency.
+    //      This is the reader of the current top of the reader data stack.
+    //      It contains the same value as fCurReaderData->fReader or NULL,
+    //      if fCurReaderData is NULL. We store it here for efficiency.
     //
     //  fEntityHandler
     //      This is the installed entity handler. Its installed via the
@@ -225,10 +287,14 @@ private :
     //      process of creating external entity readers.
     //
     //  fEntityStack
-    //      We need to keep up with which of the pushed readers are pushed
-    //      entity values that are being spooled. This is done to avoid the
-    //      problem of recursive definitions. This stack consists of refs to
-    //      EntityDecl objects for the pushed entities.
+    //      This is a storage of orphaned XMLEntityDecl objects. The
+    //      popReader() function adds a reader manager-adopted entity object
+    //      to this storage before passing its pointer to the constructor
+    //      of the being thrown EndOfEntityException exception. This makes
+    //      sure that the life-time of an entity exposed to the exception
+    //      handlers is the same as the life-time of reader manager (and so
+    //      normally the life-time of the scanner which embeds the reader
+    //      manager).
     //
     //  fNextReaderNum
     //      This is the reader serial number value. Each new reader that is
@@ -236,8 +302,8 @@ private :
     //      us catch things like partial markup errors and such.
     //
     //  fReaderStack
-    //      This is the stack of reader references. We own all the readers
-    //      and destroy them when they are used up.
+    //      This is the stack of reader data references. We own all the
+    //      entries and destroy them when they are used up.
     //
     //  fThrowEOE
     //      This flag controls whether we throw an exception when we hit an
@@ -252,12 +318,12 @@ private :
     //  fStandardUriConformant
     //      This flag controls whether we force conformant URI
     // -----------------------------------------------------------------------
-    XMLEntityDecl*              fCurEntity;
+    ReaderData*                 fCurReaderData;
     XMLReader*                  fCurReader;
     XMLEntityHandler*           fEntityHandler;
     RefStackOf<XMLEntityDecl>*  fEntityStack;
     unsigned int                fNextReaderNum;
-    RefStackOf<XMLReader>*      fReaderStack;
+    RefStackOf<ReaderData>*     fReaderStack;
     bool                        fThrowEOE;
     XMLReader::XMLVersion       fXMLVersion;
     bool                        fStandardUriConformant;