View | Details | Raw Unified | Return to bug 50539
Collapse All | Expand All

(-)src/ooxml/java/org/apache/poi/xssf/util/EvilUnclosedBRFixingInputStream.java (-7 / +40 lines)
Lines 59-64 Link Here
59
         System.arraycopy(spare, 0, b, off, spare.length);
59
         System.arraycopy(spare, 0, b, off, spare.length);
60
         int ret = spare.length;
60
         int ret = spare.length;
61
         spare = null;
61
         spare = null;
62
        // Need to do a fixup here
63
        ret = fixUp(b, off, ret);
62
         return ret;
64
         return ret;
63
      }
65
      }
64
      
66
      
Lines 73-83 Link Here
73
   }
75
   }
74
76
75
   private int fixUp(byte[] b, int offset, int read) {
77
   private int fixUp(byte[] b, int offset, int read) {
76
      // Find places to fix
78
     // Find places to fix, including partials at the end
77
      ArrayList<Integer> fixAt = new ArrayList<Integer>();
79
      ArrayList<Integer> fixAt = new ArrayList<Integer>();
78
      for(int i=offset; i<offset+read-4; i++) {
80
     for(int i=offset; i<offset+read; i++) {
79
         boolean going = true;
81
         boolean going = true;
80
         for(int j=0; j<detect.length && going; j++) {
82
        for(int j=0; j<detect.length && i+j< read && going; j++) {
81
            if(b[i+j] != detect[j]) {
83
            if(b[i+j] != detect[j]) {
82
               going = false;
84
               going = false;
83
            }
85
            }
Lines 87-99 Link Here
87
         }
89
         }
88
      }
90
      }
89
      
91
      
92
     // Nothing at all to fix 
90
      if(fixAt.size()==0) {
93
      if(fixAt.size()==0) {
91
         return read;
94
         return read;
92
      }
95
      }
93
      
96
      
94
      // Save a bit, if needed to fit
97
     // We have 4 cases here
95
      int overshoot = offset+read+fixAt.size() - b.length;  
98
     // #1 Buffer is too small and we have a split
99
     // #2 Buffer is too small and no splits
100
     // #3 Buffer is big enough but we have a split
101
     // #4 Buffer is big enough and no splits
102
     // First we check if the buffer is too small or not
103
     int overshoot = Math.max(offset+read+fixAt.size() - b.length, 0);
96
      if(overshoot > 0) {
104
      if(overshoot > 0) {
105
       // Buffer is too small so check for a split
106
       int end = b.length - overshoot;
107
       for (int i = fixAt.size()-1; i >= 0; --i) {
108
         int pos = fixAt.get(i);
109
         if (pos > (end - detect.length)) {
110
           // we have a split
111
           overshoot += (pos - (end - detect.length));
112
         } else if (pos < (end - detect.length)) break;
113
       }
114
     } else {
115
       // Buffer is big enough, but check for a split
116
       int end = b.length;
117
       for (int i = fixAt.size()-1; i >= 0; --i) {
118
         int pos = fixAt.get(i);
119
         if (pos > (end - detect.length)) {
120
           // we have a split
121
           overshoot += (pos - (end - detect.length));
122
         } else if (pos < (end - detect.length)) break;
123
       }
124
     }
125
     
126
     if (overshoot > 0) {
127
       // We need to take a bit out of the buffer so we have space to
128
       // insert the / into the <br> tag, or skip a partial <br> 
97
         spare = new byte[overshoot];
129
         spare = new byte[overshoot];
98
         System.arraycopy(b, b.length-overshoot, spare, 0, overshoot);
130
         System.arraycopy(b, b.length-overshoot, spare, 0, overshoot);
99
         read -= overshoot;
131
         read -= overshoot;
Lines 103-110 Link Here
103
      //  positions are valid
135
      //  positions are valid
104
      for(int j=fixAt.size()-1; j>=0; j--) {
136
      for(int j=fixAt.size()-1; j>=0; j--) {
105
         int i = fixAt.get(j); 
137
         int i = fixAt.get(j); 
106
138
        int xpos = read - i - 3;
107
         byte[] tmp = new byte[read-i-3];
139
        if (xpos < 0) continue;
140
        byte[] tmp = new byte[xpos];
108
         System.arraycopy(b, i+3, tmp, 0, tmp.length);
141
         System.arraycopy(b, i+3, tmp, 0, tmp.length);
109
         b[i+3] = (byte)'/';
142
         b[i+3] = (byte)'/';
110
         System.arraycopy(tmp, 0, b, i+4, tmp.length);
143
         System.arraycopy(tmp, 0, b, i+4, tmp.length);
(-)src/ooxml/testcases/org/apache/poi/xssf/util/TestEvilUnclosedBRFixingInputStream.java (+33 lines)
Lines 70-75 Link Here
70
      assertEquals(fixed, result);
70
      assertEquals(fixed, result);
71
   }
71
   }
72
   
72
   
73
   public void testBufferSize() throws Exception {
74
      byte[] orig_root = "<p><div>Hello<br>There!</div> <div>Tags!<br></div></p>".getBytes("UTF-8");
75
      byte[] fixed_root = "<p><div>Hello<br/>There!</div> <div>Tags!<br/></div></p>".getBytes("UTF-8");
76
    
77
      ByteArrayOutputStream origStream = new ByteArrayOutputStream();
78
      ByteArrayOutputStream fixedStream = new ByteArrayOutputStream();
79
      for (; fixedStream.size() < 2048 + fixed_root.length; ) {
80
	  fixedStream.write(fixed_root, 0, fixed_root.length);
81
          origStream.write(orig_root, 0, orig_root.length);
82
      }
83
      byte[] orig = origStream.toByteArray();
84
      byte[] fixed = fixedStream.toByteArray();
85
86
      EvilUnclosedBRFixingInputStream inp = new EvilUnclosedBRFixingInputStream(
87
            new ByteArrayInputStream(orig)
88
      );
89
      
90
      ByteArrayOutputStream bout = new ByteArrayOutputStream();
91
      boolean going = true;
92
      while(going) {
93
         byte[] b = new byte[1024];
94
         int r = inp.read(b);
95
         if(r > 0) {
96
            bout.write(b, 0, r);
97
         } else {
98
            going = false;
99
         }
100
      }
101
      
102
      byte[] result = bout.toByteArray();
103
      assertEquals(fixed, result);
104
   }
105
73
   protected void assertEquals(byte[] a, byte[] b) {
106
   protected void assertEquals(byte[] a, byte[] b) {
74
      assertEquals(a.length, b.length);
107
      assertEquals(a.length, b.length);
75
      for(int i=0; i<a.length; i++) {
108
      for(int i=0; i<a.length; i++) {

Return to bug 50539