Skip to content

Commit

Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
implements strict base64 encoding
Browse files Browse the repository at this point in the history
apparently the respective tests were excluded.

Sponsored by Lookout Inc.
mkristian committed Mar 17, 2015
1 parent 94bda8d commit 9a88ecf
Showing 3 changed files with 105 additions and 43 deletions.
139 changes: 97 additions & 42 deletions core/src/main/java/org/jruby/util/Pack.java
Original file line number Diff line number Diff line change
@@ -1259,61 +1259,116 @@ else if (encode.hasRemaining()) {
int index = 0;
int s = -1;

while (encode.hasRemaining()) {
a = b = c = d = -1;

// obtain a
s = safeGet(encode);
while (((a = b64_xtable[s]) == -1) && encode.hasRemaining()) {
s = safeGet(encode);
if (occurrences == 0){
if (encode.remaining()%4 != 0) {
throw runtime.newArgumentError("invalid base64");
}
if (a == -1) break;

// obtain b
s = safeGet(encode);
while (((b = b64_xtable[s]) == -1) && encode.hasRemaining()) {
while (encode.hasRemaining() && s != '=') {
a = b = c = -1;
d = -2;

// obtain a
s = safeGet(encode);
}
if (b == -1) break;

// obtain c
s = safeGet(encode);
while (((c = b64_xtable[s]) == -1) && encode.hasRemaining()) {
if (s == '=') break;
a = b64_xtable[s];
if (a == -1) throw runtime.newArgumentError("invalid base64");

// obtain b
s = safeGet(encode);
}
if ((s == '=') || c == -1) {
b = b64_xtable[s];
if (b == -1) throw runtime.newArgumentError("invalid base64");

// obtain c
s = safeGet(encode);
c = b64_xtable[s];
if (s == '=') {
encode.position(encode.position() - 1);
if (safeGet(encode) != '=') throw runtime.newArgumentError("invalid base64");
break;
}
break;
}

// obtain d
s = safeGet(encode);
while (((d = b64_xtable[s]) == -1) && encode.hasRemaining()) {
if (s == '=') break;
if (c == -1) throw runtime.newArgumentError("invalid base64");

// obtain d
s = safeGet(encode);
d = b64_xtable[s];
if (s == '=') break;
if (d == -1) throw runtime.newArgumentError("invalid base64");

// calculate based on a, b, c and d
lElem[index++] = (byte)((a << 2 | b >> 4) & 255);
lElem[index++] = (byte)((b << 4 | c >> 2) & 255);
lElem[index++] = (byte)((c << 6 | d) & 255);
}
if ((s == '=') || d == -1) {
if (s == '=') {
encode.position(encode.position() - 1);

if (encode.hasRemaining()) throw runtime.newArgumentError("invalid base64");

if (a != -1 && b != -1) {
if (c == -1 && s == '=') {
if ((b & 15) > 0) throw runtime.newArgumentError("invalid base64");
lElem[index++] = (byte)((a << 2 | b >> 4) & 255);
} else if(c != -1 && s == '=') {
if ((c & 3) > 0) throw runtime.newArgumentError("invalid base64");
lElem[index++] = (byte)((a << 2 | b >> 4) & 255);
lElem[index++] = (byte)((b << 4 | c >> 2) & 255);
}
break;
}

// calculate based on a, b, c and d
lElem[index++] = (byte)((a << 2 | b >> 4) & 255);
lElem[index++] = (byte)((b << 4 | c >> 2) & 255);
lElem[index++] = (byte)((c << 6 | d) & 255);
}
else {

if (a != -1 && b != -1) {
if (c == -1 && s == '=') {
lElem[index++] = (byte)((a << 2 | b >> 4) & 255);
} else if(c != -1 && s == '=') {
while (encode.hasRemaining()) {
a = b = c = d = -1;

// obtain a
s = safeGet(encode);
while (((a = b64_xtable[s]) == -1) && encode.hasRemaining()) {
s = safeGet(encode);
}
if (a == -1) break;

// obtain b
s = safeGet(encode);
while (((b = b64_xtable[s]) == -1) && encode.hasRemaining()) {
s = safeGet(encode);
}
if (b == -1) break;

// obtain c
s = safeGet(encode);
while (((c = b64_xtable[s]) == -1) && encode.hasRemaining()) {
if (s == '=') break;
s = safeGet(encode);
}
if ((s == '=') || c == -1) {
if (s == '=') {
encode.position(encode.position() - 1);
}
break;
}

// obtain d
s = safeGet(encode);
while (((d = b64_xtable[s]) == -1) && encode.hasRemaining()) {
if (s == '=') break;
s = safeGet(encode);
}
if ((s == '=') || d == -1) {
if (s == '=') {
encode.position(encode.position() - 1);
}
break;
}

// calculate based on a, b, c and d
lElem[index++] = (byte)((a << 2 | b >> 4) & 255);
lElem[index++] = (byte)((b << 4 | c >> 2) & 255);
lElem[index++] = (byte)((c << 6 | d) & 255);
}

if (a != -1 && b != -1) {
if (c == -1 && s == '=') {
lElem[index++] = (byte)((a << 2 | b >> 4) & 255);
} else if(c != -1 && s == '=') {
lElem[index++] = (byte)((a << 2 | b >> 4) & 255);
lElem[index++] = (byte)((b << 4 | c >> 2) & 255);
}
}
}
result.append(RubyString.newString(runtime, new ByteList(lElem, 0, index,
1 change: 0 additions & 1 deletion test/externals/ruby1.9/excludes/TestBase64.rb

This file was deleted.

8 changes: 8 additions & 0 deletions test/test_base64_strangeness.rb
Original file line number Diff line number Diff line change
@@ -9,3 +9,11 @@ def test_base64_strangeness
assert !Class.private_instance_methods.include?('encode64')
end
end

# be strict GH-2551
class TestBase64Strangeness < Test::Unit::TestCase
def test_base64_stictness
require 'base64'
assert_raise(ArgumentError) { Base64.strict_decode64("AA==AAAA") }
end
end if RUBY_VERSION >= '1.9'

0 comments on commit 9a88ecf

Please sign in to comment.