~ubuntu-branches/debian/sid/subversion/sid

« back to all changes in this revision

Viewing changes to subversion/bindings/javahl/native/jniwrapper/jni_channel.cpp

  • Committer: Package Import Robot
  • Author(s): James McCoy
  • Date: 2015-08-07 21:32:47 UTC
  • mfrom: (0.2.15) (4.1.7 experimental)
  • Revision ID: package-import@ubuntu.com-20150807213247-ozyewtmgsr6tkewl
Tags: 1.9.0-1
* Upload to unstable
* New upstream release.
  + Security fixes
    - CVE-2015-3184: Mixed anonymous/authenticated path-based authz with
      httpd 2.4
    - CVE-2015-3187: svn_repos_trace_node_locations() reveals paths hidden
      by authz
* Add >= 2.7 requirement for python-all-dev Build-Depends, needed to run
  tests.
* Remove Build-Conflicts against ruby-test-unit.  (Closes: #791844)
* Remove patches/apache_module_dependency in favor of expressing the
  dependencies in authz_svn.load/dav_svn.load.
* Build-Depend on apache2-dev (>= 2.4.16) to ensure ap_some_authn_required()
  is available when building mod_authz_svn and Depend on apache2-bin (>=
  2.4.16) for runtime support.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/**
 
2
 * @copyright
 
3
 * ====================================================================
 
4
 *    Licensed to the Apache Software Foundation (ASF) under one
 
5
 *    or more contributor license agreements.  See the NOTICE file
 
6
 *    distributed with this work for additional information
 
7
 *    regarding copyright ownership.  The ASF licenses this file
 
8
 *    to you under the Apache License, Version 2.0 (the
 
9
 *    "License"); you may not use this file except in compliance
 
10
 *    with the License.  You may obtain a copy of the License at
 
11
 *
 
12
 *      http://www.apache.org/licenses/LICENSE-2.0
 
13
 *
 
14
 *    Unless required by applicable law or agreed to in writing,
 
15
 *    software distributed under the License is distributed on an
 
16
 *    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 
17
 *    KIND, either express or implied.  See the License for the
 
18
 *    specific language governing permissions and limitations
 
19
 *    under the License.
 
20
 * ====================================================================
 
21
 * @endcopyright
 
22
 */
 
23
 
 
24
#include <stdexcept>
 
25
 
 
26
#include "jni_object.hpp"
 
27
#include "jni_array.hpp"
 
28
#include "jni_channel.hpp"
 
29
 
 
30
#include "svn_private_config.h"
 
31
 
 
32
namespace Java {
 
33
 
 
34
namespace {
 
35
// Get the ByteBuffer's internal array.
 
36
jbyteArray get_array(Env env, jobject buffer,
 
37
                     const MethodID& mid_has_array,
 
38
                     const MethodID& mid_get_array)
 
39
{
 
40
  if (!env.CallBooleanMethod(buffer, mid_has_array))
 
41
    return NULL;
 
42
  return jbyteArray(env.CallObjectMethod(buffer, mid_get_array));
 
43
}
 
44
 
 
45
// Get the offset in the ByteBuffer's array. NEVER call this function
 
46
// unless the buffer actually has an accessible array.
 
47
jint get_array_offset(Env env, jobject buffer,
 
48
                      const MethodID& mid_get_array_offset)
 
49
{
 
50
  return env.CallIntMethod(buffer, mid_get_array_offset);
 
51
}
 
52
 
 
53
// Get the remaining space in a ByteBuffer.
 
54
jint get_remaining(Env env, jobject buffer,
 
55
                   const MethodID& mid_get_remaining)
 
56
{
 
57
  return env.CallIntMethod(buffer, mid_get_remaining);
 
58
}
 
59
 
 
60
// Get the current position of a ByteBuffer.
 
61
jint get_position(Env env, jobject buffer,
 
62
                  const MethodID& mid_get_position)
 
63
{
 
64
  return env.CallIntMethod(buffer, mid_get_position);
 
65
}
 
66
 
 
67
// Set the new position of a ByteBuffer.
 
68
void set_position(Env env, jobject buffer,
 
69
                  const MethodID& mid_set_position,
 
70
                  jint new_position)
 
71
{
 
72
  env.CallObjectMethod(buffer, mid_set_position, new_position);
 
73
}
 
74
 
 
75
// Get byte array contents from a ByteBuffer.
 
76
void get_bytearray(Env env, jobject buffer,
 
77
                   const MethodID& mid_get_bytearray,
 
78
                   ByteArray& array, jint length = -1, jint offset = 0)
 
79
{
 
80
  env.CallObjectMethod(
 
81
      buffer, mid_get_bytearray, array.get(), offset,
 
82
      (length >= 0 ? length : (array.length() - offset)));
 
83
}
 
84
 
 
85
// Put byte array contents into a ByteBuffer.
 
86
void put_bytearray(Env env, jobject buffer,
 
87
                   const MethodID& mid_put_bytearray,
 
88
                   ByteArray& array, jint length = -1, jint offset = 0)
 
89
{
 
90
  env.CallObjectMethod(buffer, mid_put_bytearray,
 
91
                       array.get(), offset,
 
92
                       (length >= 0 ? length : (array.length() - offset)));
 
93
}
 
94
 
 
95
struct BadReaderWriter : public ChannelReader, ChannelWriter
 
96
{
 
97
  BadReaderWriter() {}
 
98
 
 
99
  virtual jint operator()(Env, void*, jint)
 
100
    {
 
101
      throw std::logic_error(_("Reading from write-only channel"));
 
102
    }
 
103
 
 
104
  virtual jint operator()(Env, const void*, jint)
 
105
    {
 
106
      throw std::logic_error(_("Writing to read-only channel"));
 
107
    }
 
108
} bad_reader_writer;
 
109
 
 
110
} // anonymous namespace
 
111
 
 
112
 
 
113
ChannelReader& ByteChannel::m_null_reader = bad_reader_writer;
 
114
ChannelWriter& ByteChannel::m_null_writer = bad_reader_writer;
 
115
 
 
116
const char* const ByteChannel::ByteBuffer::m_class_name =
 
117
  "java/nio/ByteBuffer";
 
118
 
 
119
ByteChannel::ByteBuffer::ClassImpl::ClassImpl(Env env, jclass cls)
 
120
  : Object::ClassImpl(env, cls),
 
121
    m_mid_has_array(env.GetMethodID(cls, "hasArray", "()Z")),
 
122
    m_mid_get_array(env.GetMethodID(cls, "array", "()[B")),
 
123
    m_mid_get_array_offset(env.GetMethodID(cls, "arrayOffset", "()I")),
 
124
    m_mid_get_remaining(env.GetMethodID(cls, "remaining", "()I")),
 
125
    m_mid_get_position(env.GetMethodID(cls, "position", "()I")),
 
126
    m_mid_set_position(env.GetMethodID(cls,  "position",
 
127
                                       "(I)Ljava/nio/Buffer;")),
 
128
    m_mid_get_bytearray(env.GetMethodID(cls, "get",
 
129
                                        "([BII)Ljava/nio/ByteBuffer;")),
 
130
    m_mid_put_bytearray(env.GetMethodID(cls, "put",
 
131
                                        "([BII)Ljava/nio/ByteBuffer;"))
 
132
{}
 
133
 
 
134
ByteChannel::ByteBuffer::ClassImpl::~ClassImpl() {}
 
135
 
 
136
jint ByteChannel::read(jobject destination)
 
137
{
 
138
  const ByteBuffer::ClassImpl& bufimpl = ByteBuffer::impl(m_env);
 
139
 
 
140
  const jint remaining = get_remaining(m_env, destination,
 
141
                                       bufimpl.m_mid_get_remaining);
 
142
  if (!remaining)
 
143
    {
 
144
      // No space in the buffer; don't try to read anything.
 
145
      return 0;
 
146
    }
 
147
 
 
148
  const jint position = get_position(m_env, destination,
 
149
                                     bufimpl.m_mid_get_position);
 
150
 
 
151
  jint bytes_read = 0;
 
152
  void* data = m_env.GetDirectBufferAddress(destination);
 
153
  if (data)
 
154
    {
 
155
      data = static_cast<char*>(data) + position;
 
156
      bytes_read = m_reader(m_env, data, remaining);
 
157
    }
 
158
  else
 
159
    {
 
160
      // It was not a direct buffer ... see if it has an array.
 
161
      jbyteArray raw_array = get_array(m_env, destination,
 
162
                                       bufimpl.m_mid_has_array,
 
163
                                       bufimpl.m_mid_get_array);
 
164
      if (raw_array)
 
165
        {
 
166
          const jint array_offset = get_array_offset(
 
167
              m_env, destination,
 
168
              bufimpl.m_mid_get_array_offset);
 
169
          ByteArray array(m_env, raw_array);
 
170
          ByteArray::MutableContents contents(array);
 
171
          data = contents.data();
 
172
          data = static_cast<char*>(data) + position + array_offset;
 
173
          bytes_read = m_reader(m_env, data, remaining);
 
174
        }
 
175
    }
 
176
  if (data)
 
177
    {
 
178
      if (bytes_read > 0)
 
179
        set_position(m_env, destination,
 
180
                     bufimpl.m_mid_set_position,
 
181
                     position + bytes_read);
 
182
      return bytes_read;
 
183
    }
 
184
 
 
185
  // No accessible array, either. Oh well. Create a byte array and
 
186
  // push it into the buffer.
 
187
  ByteArray array(m_env, remaining);
 
188
  ByteArray::MutableContents contents(array);
 
189
  bytes_read = m_reader(m_env, contents.data(), contents.length());
 
190
  if (bytes_read > 0)
 
191
    put_bytearray(m_env, destination,
 
192
                  bufimpl.m_mid_put_bytearray,
 
193
                  array, bytes_read);
 
194
  return bytes_read;
 
195
}
 
196
 
 
197
jint ByteChannel::write(jobject source)
 
198
{
 
199
  const ByteBuffer::ClassImpl& bufimpl = ByteBuffer::impl(m_env);
 
200
 
 
201
  const jint remaining = get_remaining(m_env, source,
 
202
                                       bufimpl.m_mid_get_remaining);
 
203
  if (!remaining)
 
204
    {
 
205
      // No data in the buffer; don't try to write anything.
 
206
      return 0;
 
207
    }
 
208
 
 
209
  const jint position = get_position(m_env, source,
 
210
                                     bufimpl.m_mid_get_position);
 
211
 
 
212
  jint bytes_written = 0;
 
213
  const void* data = m_env.GetDirectBufferAddress(source);
 
214
  if (data)
 
215
    {
 
216
      data = static_cast<const char*>(data) + position;
 
217
      bytes_written = m_writer(m_env, data, remaining);
 
218
    }
 
219
  else
 
220
    {
 
221
      // It was not a direct buffer ... see if it has an array.
 
222
      jbyteArray raw_array = get_array(m_env, source,
 
223
                                       bufimpl.m_mid_has_array,
 
224
                                       bufimpl.m_mid_get_array);
 
225
      if (raw_array)
 
226
        {
 
227
          const jint array_offset = get_array_offset(
 
228
              m_env, source,
 
229
              bufimpl.m_mid_get_array_offset);
 
230
          const ByteArray array(m_env, raw_array);
 
231
          ByteArray::Contents contents(array);
 
232
          data = contents.data();
 
233
          data = static_cast<const char*>(data) + position + array_offset;
 
234
          bytes_written = m_writer(m_env, data, remaining);
 
235
        }
 
236
    }
 
237
  if (data)
 
238
    {
 
239
      if (bytes_written > 0)
 
240
        set_position(m_env, source,
 
241
                     bufimpl.m_mid_set_position,
 
242
                     position + bytes_written);
 
243
      return bytes_written;
 
244
    }
 
245
 
 
246
  // No accessible array, either. Oh well. Get an array from the
 
247
  // buffer and read data from that.
 
248
  ByteArray array(m_env, remaining);
 
249
  get_bytearray(m_env, source,
 
250
                bufimpl.m_mid_get_bytearray,
 
251
                array);
 
252
  ByteArray::Contents contents(array);
 
253
  bytes_written = m_writer(m_env, contents.data(), contents.length());
 
254
  return bytes_written;
 
255
}
 
256
 
 
257
} // namespace Java