This file is indexed.

/usr/include/dcmtk/dcmdata/dcrledec.h is in libdcmtk-dev 3.6.2-3build3.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  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
/*
 *
 *  Copyright (C) 1994-2011, OFFIS e.V.
 *  All rights reserved.  See COPYRIGHT file for details.
 *
 *  This software and supporting documentation were developed by
 *
 *    OFFIS e.V.
 *    R&D Division Health
 *    Escherweg 2
 *    D-26121 Oldenburg, Germany
 *
 *
 *  Module:  dcmdata
 *
 *  Author:  Marco Eichelberg
 *
 *  Purpose: RLE decompressor
 *
 */

#ifndef DCRLEDEC_H
#define DCRLEDEC_H

#include "dcmtk/config/osconfig.h"
#include "dcmtk/dcmdata/dcerror.h"

/** this class implements an RLE decompressor conforming to the DICOM standard.
 *  The class is loosely based on an implementation by Phil Norman <forrey@eh.org>
 */
class DCMTK_DCMDATA_EXPORT DcmRLEDecoder
{
public:

  /** constructor
   *  @param outputBufferSize size of the output buffer (in bytes)
   *    to which the RLE codec will write decompressed output.
   */
  DcmRLEDecoder(size_t outputBufferSize)
  : fail_(0)
  , outputBufferSize_(outputBufferSize)
  , outputBuffer_(NULL)
  , offset_(0)
  , suspendInfo_(128)
  {
    if (outputBufferSize_ == 0) fail_ = 1;
    else
    {
      outputBuffer_ = new unsigned char[outputBufferSize_];
      if (outputBuffer_ == NULL) fail_ = 1;
    }
  }

  /// destructor
  ~DcmRLEDecoder()
  {
    delete[] outputBuffer_;
  }

  /** resets the decoder object to newly constructed state.
   *  The size and location of the output buffer is not changed.
   */
  inline void clear()
  {
    offset_ = 0;
    suspendInfo_ = 128;
    if (outputBuffer_) fail_ = 0;
  }


  inline OFCondition decompress(void *compressedData, size_t compressedSize)
  {
    // we allow a call for zero bytes
    if (compressedSize == 0) return EC_Normal;

    OFCondition result = EC_IllegalCall;

    // check parameters passed by caller
    if (compressedData == NULL) fail_ = 1;

    if (! fail_)  // if fail_ is true, just ignore input
    {
      result = EC_Normal;
      unsigned char ch;
      unsigned char nbytes;
      unsigned char *cp = OFstatic_cast(unsigned char *, compressedData);

      // check if we suspended last time, clean up
      if (suspendInfo_ > 128)
      {
        // DICOM packbit scheme uses 257 - nbytes to represent replicate runs
        nbytes = OFstatic_cast(unsigned char, 257 - suspendInfo_);

        // suspended replicate run. compressedSize cannot be zero now.
        suspendInfo_ = 128;

        ch = *cp++;
        --compressedSize;
        replicate(ch, nbytes);
      }
      else if (suspendInfo_ < 128)
      {
        // suspended literal run
        nbytes = OFstatic_cast(unsigned char, (suspendInfo_ & 0x7f) + 1);
        suspendInfo_ = 128;
        if (compressedSize < nbytes)
        {
          // we're going to suspend again (oops?), prepare everything
          suspendInfo_ = OFstatic_cast(unsigned char, nbytes - compressedSize - 1);
          nbytes = OFstatic_cast(unsigned char, compressedSize);
          result = EC_StreamNotifyClient;
        }

        literal(cp, nbytes);
        compressedSize -= nbytes;
        cp += nbytes;
      }

      // continue with ordinary RLE decompression
      while (compressedSize && (! fail_))
      {
        ch = *cp++;
        --compressedSize;

        if (ch & 0x80)
        {
          // replicate run
          if (compressedSize)
          {
            // DICOM packbit scheme uses 257 - nbytes to represent replicate runs
            nbytes = OFstatic_cast(unsigned char, 257 - ch);
            ch = *cp++;
            --compressedSize;
            replicate(ch, nbytes);
          }
          else
          {
            // suspension: replicate run but second byte is in next block
            suspendInfo_ = ch;
            result = EC_StreamNotifyClient;
          }
        } 
        else
        {
          // literal run
          nbytes = OFstatic_cast(unsigned char, (ch & 0x7f) + 1);
          if (compressedSize < nbytes)
          {
            // we're going to suspend, prepare everything
            suspendInfo_ = OFstatic_cast(unsigned char, nbytes - compressedSize - 1);
            nbytes = OFstatic_cast(unsigned char, compressedSize);
            result = EC_StreamNotifyClient;
          }

          literal(cp, nbytes);
          compressedSize -= nbytes;
          cp += nbytes;
        }
      }

      // failure status at this point means output buffer overflow
      if (fail_) result = EC_CorruptedData;
    }

    return result;
  }


  /** returns the number of bytes written to the output buffer
   *  @return size of decompressed stream, in bytes
   */
  inline size_t size() const
  {
    return offset_;
  }

  /** returns pointer to the output buffer
   */
  inline void *getOutputBuffer() const
  {
    return outputBuffer_;
  }

  /** returns true if the RLE compressor has failed (out of memory or output buffer too small).
   */
  inline OFBool fail() const
  {
    if (fail_) return OFTrue; else return OFFalse;
  }

private:

  /// private undefined copy constructor
  DcmRLEDecoder(const DcmRLEDecoder&);

  /// private undefined copy assignment operator
  DcmRLEDecoder& operator=(const DcmRLEDecoder&);


  /** this method expands a replicate run
   *  @param ch value to replicate
   *  @param nbytes number of repetitions
   */
  inline void replicate(unsigned char ch, unsigned char nbytes)
  {
     if (offset_ + nbytes > outputBufferSize_)
     {
       // output buffer overflow
       fail_ = 1;
       nbytes = OFstatic_cast(unsigned char, outputBufferSize_ - offset_);
     }

     while (nbytes--) outputBuffer_[offset_++] = ch;
  }


  /** this method expands a literal run
   *  @param cp pointer to buffer
   *  @param nbytes number of bytes in buffer
   */
  inline void literal(unsigned char *cp, unsigned char nbytes)
  {
     if (offset_ + nbytes > outputBufferSize_)
     {
       // output buffer overflow
       fail_ = 1;
       nbytes = OFstatic_cast(unsigned char, outputBufferSize_ - offset_);
     }

     while (nbytes--) outputBuffer_[offset_++] = *cp++;
  }

  /* member variables */

  /** this flag indicates a failure of the RLE codec.  Once a failure is
   *  flagged, the codec will consume all input and not produce any more
   *  output.
   */
  int fail_;

  /** size of output buffer, in bytes
   */
  size_t outputBufferSize_;

  /** this member points to a block of size outputBufferSize_
   *  (unless fail_ is true). This is the block of data to
   *  which the decompressed stream is written
   */
  unsigned char *outputBuffer_;

  /** contains the number of bytes already written to outputBuffer_.
   *  Value is always less or equal to outputBufferSize_.
   */
  size_t offset_;

  /** contains suspension information.  
   *  If not suspended, contains 128.
   *  If suspended during a replicate run, contains control byte of repeat run (> 128).
   *  If suspended during a literal run, contains number of remaining bytes in literal run minus 1 (< 128).
   */
  unsigned char suspendInfo_;
};

#endif