2014-09-08 21:25:53 +00:00
|
|
|
# -*- coding:binary -*-
|
|
|
|
require 'spec_helper'
|
|
|
|
|
|
|
|
require 'rex/encoder/xdr'
|
|
|
|
|
|
|
|
describe Rex::Encoder::XDR do
|
|
|
|
|
|
|
|
describe ".encode_int" do
|
|
|
|
subject { described_class.encode_int(int) }
|
|
|
|
let(:int) { 0x41424344 }
|
|
|
|
|
|
|
|
it "returns an String" do
|
|
|
|
is_expected.to be_kind_of(String)
|
|
|
|
end
|
|
|
|
|
|
|
|
it "encodes big endian 32 bit usigned integer" do
|
|
|
|
is_expected.to eq("\x41\x42\x43\x44")
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
describe ".decode_int!" do
|
|
|
|
subject { described_class.decode_int!(data) }
|
|
|
|
|
|
|
|
context "when data is nil" do
|
|
|
|
let(:data) { nil }
|
|
|
|
it "returns 0" do
|
|
|
|
is_expected.to be(0)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context "when data is empty" do
|
|
|
|
let(:data) { '' }
|
|
|
|
|
|
|
|
it "returns nil" do
|
|
|
|
is_expected.to be_nil
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context "when data is 1-4 bytes length" do
|
|
|
|
let(:data) { "\x41\x42\x43\x44" }
|
|
|
|
|
|
|
|
it "unpacks big endian 32bit unsigned int" do
|
|
|
|
is_expected.to eq(0x41424344)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context "when data is bigger than 4 bytes" do
|
|
|
|
let(:data) { "\x41\x42\x43\x44\x45" }
|
|
|
|
|
|
|
|
it "unpacks just one big endian 32bit unsigned int" do
|
|
|
|
is_expected.to eq(0x41424344)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
describe ".encode_lchar" do
|
|
|
|
subject { described_class.encode_lchar(char) }
|
|
|
|
|
|
|
|
context "when char & 0x80 == 0" do
|
|
|
|
let(:char) { 0x80 }
|
|
|
|
|
2014-09-08 23:17:24 +00:00
|
|
|
it "encodes char byte as integer with sign extended" do
|
2014-09-08 21:25:53 +00:00
|
|
|
is_expected.to eq("\xff\xff\xff\x80")
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context "when char & 0x80 != 0" do
|
|
|
|
let(:char) { 0x41 }
|
|
|
|
|
2014-09-08 23:17:24 +00:00
|
|
|
it "encodes char byte as integer" do
|
2014-09-08 21:25:53 +00:00
|
|
|
is_expected.to eq("\x00\x00\x00\x41")
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
describe ".decode_lchar!" do
|
|
|
|
subject { described_class.decode_lchar!(data) }
|
|
|
|
|
|
|
|
context "when data's length is equal or greater than 4" do
|
|
|
|
let(:data) { "\x41\x42\x43\x44" }
|
|
|
|
|
|
|
|
it "returns char code for last byte" do
|
|
|
|
is_expected.to eq("D")
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context "when data's length is less than 4" do
|
|
|
|
let(:data) { "\x41" }
|
|
|
|
|
|
|
|
it "raises an error" do
|
|
|
|
expect { subject }.to raise_error(NoMethodError)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
describe ".encode_string" do
|
|
|
|
subject { described_class.encode_string(str, max) }
|
|
|
|
|
|
|
|
context "when data is bigger than max" do
|
|
|
|
let(:str) { "ABCDE" }
|
|
|
|
let(:max) { 4 }
|
|
|
|
|
|
|
|
it "raises an error" do
|
|
|
|
expect { subject }.to raise_error(ArgumentError)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context "when data is shorter or equal to max" do
|
|
|
|
let(:str) { "ABCDE" }
|
|
|
|
let(:max) { 5 }
|
|
|
|
|
|
|
|
it "returns an String" do
|
|
|
|
is_expected.to be_kind_of(String)
|
|
|
|
end
|
|
|
|
|
|
|
|
it "prefix encoded length" do
|
|
|
|
is_expected.to start_with("\x00\x00\x00\x05")
|
|
|
|
end
|
|
|
|
|
|
|
|
it "returns the encoded string padded with zeros" do
|
|
|
|
is_expected.to eq("\x00\x00\x00\x05ABCDE\x00\x00\x00")
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
describe ".decode_string!" do
|
|
|
|
subject { described_class.decode_string!(data) }
|
|
|
|
|
|
|
|
context "when encoded string length is 0" do
|
|
|
|
let(:data) { "\x00\x00\x00\x00" }
|
|
|
|
|
|
|
|
it "returns empty string" do
|
|
|
|
is_expected.to eq("")
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context "when string contains padding" do
|
|
|
|
let(:data) {"\x00\x00\x00\x03ABC00000"}
|
|
|
|
|
|
|
|
it "returns string without padding" do
|
|
|
|
is_expected.to eq("ABC")
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2014-09-08 23:17:24 +00:00
|
|
|
context "when fake length" do
|
|
|
|
context "and no string" do
|
|
|
|
let(:data) { "\x00\x00\x00\x03" }
|
2014-09-08 21:25:53 +00:00
|
|
|
|
2014-09-08 23:17:24 +00:00
|
|
|
it "returns empty string" do
|
|
|
|
is_expected.to eq("")
|
|
|
|
end
|
2014-09-08 21:25:53 +00:00
|
|
|
end
|
|
|
|
|
2014-09-08 23:17:24 +00:00
|
|
|
context "longer than real string length" do
|
|
|
|
let(:data) { "\x00\x00\x00\x08ABCD" }
|
2014-09-08 21:25:53 +00:00
|
|
|
|
2014-09-08 23:17:24 +00:00
|
|
|
it "returns available string" do
|
|
|
|
is_expected.to eq("ABCD")
|
|
|
|
end
|
2014-09-08 21:25:53 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
2014-09-08 22:12:04 +00:00
|
|
|
|
2014-09-08 23:05:09 +00:00
|
|
|
describe ".encode_varray" do
|
|
|
|
subject { described_class.encode_varray(arr, max) }
|
|
|
|
|
|
|
|
context "when arr length is bigger than max" do
|
|
|
|
let(:arr) { [1, 2, 3] }
|
|
|
|
let(:max) { 2 }
|
|
|
|
it "raises an error" do
|
|
|
|
expect { subject }.to raise_error(ArgumentError)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context "when arr length is minor or equal than max" do
|
|
|
|
let(:arr) { [0x41414141, 0x42424242, 0x43434343] }
|
|
|
|
let(:max) { 3 }
|
|
|
|
|
|
|
|
it "returns an String" do
|
|
|
|
expect(described_class.encode_varray(arr, max) { |i| described_class.encode_int(i) }).to be_kind_of(String)
|
|
|
|
end
|
|
|
|
|
2014-09-08 23:17:24 +00:00
|
|
|
it "prefixes encoded length" do
|
2014-09-08 23:05:09 +00:00
|
|
|
expect(described_class.encode_varray(arr, max) { |i| described_class.encode_int(i) }).to start_with("\x00\x00\x00\x03")
|
|
|
|
end
|
|
|
|
|
|
|
|
it "returns the encoded array" do
|
|
|
|
expect(described_class.encode_varray(arr, max) { |i| described_class.encode_int(i) }).to eq("\x00\x00\x00\x03\x41\x41\x41\x41\x42\x42\x42\x42\x43\x43\x43\x43")
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2014-09-08 22:12:04 +00:00
|
|
|
describe ".decode_varray!" do
|
|
|
|
subject { described_class.decode_varray!(data) }
|
|
|
|
|
2014-09-08 23:17:24 +00:00
|
|
|
context "when encoded length is 0" do
|
2014-09-08 22:12:04 +00:00
|
|
|
let(:data) { "\x00\x00\x00\x00" }
|
|
|
|
|
|
|
|
it "returns an empty array" do
|
|
|
|
is_expected.to eq([])
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2014-09-08 23:17:24 +00:00
|
|
|
context "when fake encoded length" do
|
|
|
|
context "and no values" do
|
|
|
|
let(:data) { "\x00\x00\x00\x02" }
|
2014-09-08 22:12:04 +00:00
|
|
|
|
2014-09-08 23:17:24 +00:00
|
|
|
it "returns an Array filled with nils" do
|
|
|
|
expect(described_class.decode_varray!(data) { |s| described_class.decode_int!(s) }).to eq([nil, nil])
|
|
|
|
end
|
2014-09-08 22:12:04 +00:00
|
|
|
end
|
|
|
|
|
2014-09-08 23:17:24 +00:00
|
|
|
context "longer than available values" do
|
|
|
|
let(:data) { "\x00\x00\x00\x02\x00\x00\x00\x41" }
|
2014-09-08 22:12:04 +00:00
|
|
|
|
2014-09-08 23:17:24 +00:00
|
|
|
it "returns Array padded with nils" do
|
|
|
|
expect(described_class.decode_varray!(data) { |s| described_class.decode_int!(s) }).to eq([0x41, nil])
|
|
|
|
end
|
2014-09-08 22:12:04 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context "when valid encoded data" do
|
|
|
|
let(:data) { "\x00\x00\x00\x02\x41\x42\x43\x44\x00\x00\x00\x11"}
|
|
|
|
it "retuns Array with decoded values" do
|
|
|
|
expect(described_class.decode_varray!(data) { |s| described_class.decode_int!(s) }).to eq([0x41424344, 0x11])
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2014-09-08 23:05:09 +00:00
|
|
|
describe ".encode" do
|
|
|
|
it "encodes integers" do
|
|
|
|
expect(described_class.encode(1)).to eq("\x00\x00\x00\x01")
|
|
|
|
end
|
|
|
|
|
|
|
|
it "encodes arrays" do
|
|
|
|
expect(described_class.encode([0x41414141, 0x42424242])).to eq("\x00\x00\x00\x02\x41\x41\x41\x41\x42\x42\x42\x42")
|
|
|
|
end
|
|
|
|
|
|
|
|
it "encodes strings" do
|
|
|
|
expect(described_class.encode("ABCD")).to eq("\x00\x00\x00\x04\x41\x42\x43\x44")
|
|
|
|
end
|
|
|
|
|
|
|
|
it "encodes mixed type of elements" do
|
|
|
|
expect(described_class.encode(1, [0x41414141], "ABCD")).to eq("\x00\x00\x00\x01\x00\x00\x00\x01\x41\x41\x41\x41\x00\x00\x00\x04\x41\x42\x43\x44")
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
describe ".decode!" do
|
|
|
|
|
|
|
|
context "when no type arguments" do
|
|
|
|
it "retuns empty Array" do
|
|
|
|
expect(described_class.decode!("\x41\x41\x41\x41")).to eq([])
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context "when not enough data" do
|
|
|
|
it "retuns Array filled with nils" do
|
|
|
|
expect(described_class.decode!("", Array)).to eq([nil])
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
it "decodes integers" do
|
|
|
|
expect(described_class.decode!("\x41\x41\x41\x41", Integer)).to eq([0x41414141])
|
|
|
|
end
|
|
|
|
|
|
|
|
it "decodes arrays" do
|
|
|
|
expect(described_class.decode!("\x00\x00\x00\x01\x41\x41\x41\x41", [Integer])).to eq([[0x41414141]])
|
|
|
|
end
|
|
|
|
|
|
|
|
it "decodes strings" do
|
|
|
|
expect(described_class.decode!("\x00\x00\x00\x01\x41", String)).to eq(["A"])
|
|
|
|
end
|
|
|
|
|
|
|
|
it "decodes mixed elements" do
|
|
|
|
expect(described_class.decode!("\x41\x41\x41\x41\x00\x00\x00\x01\x41\x00\x00\x00\x00\x00\x00\x01\x42\x42\x42\x42", Integer, String, [Integer])).to eq([0x41414141, "A", [0x42424242]])
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2014-09-08 21:25:53 +00:00
|
|
|
end
|