BinaryUtil.java

1
// Copyright (c) 2018, Yubico AB
2
// All rights reserved.
3
//
4
// Redistribution and use in source and binary forms, with or without
5
// modification, are permitted provided that the following conditions are met:
6
//
7
// 1. Redistributions of source code must retain the above copyright notice, this
8
//    list of conditions and the following disclaimer.
9
//
10
// 2. Redistributions in binary form must reproduce the above copyright notice,
11
//    this list of conditions and the following disclaimer in the documentation
12
//    and/or other materials provided with the distribution.
13
//
14
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
15
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
18
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
20
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
21
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
22
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24
25
package com.yubico.internal.util;
26
27
import java.io.IOException;
28
import java.io.InputStream;
29
import java.nio.ByteBuffer;
30
import java.nio.ByteOrder;
31
import java.util.Arrays;
32
33
public class BinaryUtil {
34
35
  public static byte[] copy(byte[] bytes) {
36 1 1. copy : replaced return value with null for com/yubico/internal/util/BinaryUtil::copy → NO_COVERAGE
    return Arrays.copyOf(bytes, bytes.length);
37
  }
38
39
  /**
40
   * @param bytes Bytes to encode
41
   */
42
  public static String toHex(final byte[] bytes) {
43 1 1. toHex : Replaced integer multiplication with division → KILLED
    final char[] digits = new char[bytes.length * 2];
44 2 1. toHex : negated conditional → KILLED
2. toHex : changed conditional boundary → KILLED
    for (int i = 0; i < bytes.length; ++i) {
45 1 1. toHex : Replaced integer multiplication with division → KILLED
      final int i2 = i * 2;
46 2 1. toHex : Replaced Shift Right with Shift Left → KILLED
2. toHex : Replaced bitwise AND with OR → KILLED
      digits[i2] = Character.forDigit((bytes[i] >> 4) & 0x0f, 16);
47 2 1. toHex : Replaced bitwise AND with OR → KILLED
2. toHex : Replaced integer addition with subtraction → KILLED
      digits[i2 + 1] = Character.forDigit(bytes[i] & 0x0f, 16);
48
    }
49 1 1. toHex : replaced return value with "" for com/yubico/internal/util/BinaryUtil::toHex → KILLED
    return new String(digits);
50
  }
51
52
  /**
53
   * @param hex String of hexadecimal digits to decode as bytes.
54
   */
55
  public static byte[] fromHex(final String hex) {
56 2 1. fromHex : negated conditional → KILLED
2. fromHex : Replaced integer modulus with multiplication → KILLED
    if (hex.length() % 2 != 0) {
57
      throw new IllegalArgumentException("Length of hex string is not even: " + hex);
58
    }
59
60 1 1. fromHex : Replaced integer division with multiplication → KILLED
    final byte[] result = new byte[hex.length() / 2];
61 2 1. fromHex : changed conditional boundary → KILLED
2. fromHex : negated conditional → KILLED
    for (int i = 0; i < hex.length(); ++i) {
62
      final int d = Character.digit(hex.charAt(i), 16);
63 2 1. fromHex : changed conditional boundary → KILLED
2. fromHex : negated conditional → KILLED
      if (d < 0) {
64
        throw new IllegalArgumentException("Invalid hex digit at index " + i + " in: " + hex);
65
      }
66 6 1. fromHex : Replaced integer multiplication with division → KILLED
2. fromHex : Replaced integer addition with subtraction → KILLED
3. fromHex : Replaced Shift Left with Shift Right → KILLED
4. fromHex : Replaced bitwise OR with AND → KILLED
5. fromHex : Replaced integer modulus with multiplication → KILLED
6. fromHex : Replaced integer division with multiplication → KILLED
      result[i / 2] |= d << (((i + 1) % 2) * 4);
67
    }
68 1 1. fromHex : replaced return value with null for com/yubico/internal/util/BinaryUtil::fromHex → KILLED
    return result;
69
  }
70
71
  /**
72
   * Parse a single byte from two hexadecimal characters.
73
   *
74
   * @param hex String of hexadecimal digits to decode as bytes.
75
   */
76
  public static byte singleFromHex(String hex) {
77 1 1. singleFromHex : removed call to com/yubico/internal/util/ExceptionUtil::assertTrue → NO_COVERAGE
    ExceptionUtil.assertTrue(
78 1 1. singleFromHex : negated conditional → NO_COVERAGE
        hex.length() == 2, "Argument must be exactly 2 hexadecimal characters, was: %s", hex);
79 1 1. singleFromHex : replaced byte return with 0 for com/yubico/internal/util/BinaryUtil::singleFromHex → NO_COVERAGE
    return fromHex(hex)[0];
80
  }
81
82
  /**
83
   * Read one byte as an unsigned 8-bit integer.
84
   *
85
   * <p>Result is of type <code>short</code> because Java doesn't have unsigned types.
86
   *
87
   * @return A value between 0 and 255, inclusive.
88
   */
89
  public static short getUint8(byte b) {
90
    // Prepend a zero so we can parse it as a signed int16 instead of a signed int8
91 1 1. getUint8 : replaced short return with 0 for com/yubico/internal/util/BinaryUtil::getUint8 → KILLED
    return ByteBuffer.wrap(new byte[] {0, b}).order(ByteOrder.BIG_ENDIAN).getShort();
92
  }
93
94
  /**
95
   * Read 2 bytes as a big endian unsigned 16-bit integer.
96
   *
97
   * <p>Result is of type <code>int</code> because Java doesn't have unsigned types.
98
   *
99
   * @return A value between 0 and 2^16- 1, inclusive.
100
   */
101
  public static int getUint16(byte[] bytes) {
102 1 1. getUint16 : negated conditional → KILLED
    if (bytes.length == 2) {
103
      // Prepend zeroes so we can parse it as a signed int32 instead of a signed int16
104 1 1. getUint16 : replaced int return with 0 for com/yubico/internal/util/BinaryUtil::getUint16 → KILLED
      return ByteBuffer.wrap(new byte[] {0, 0, bytes[0], bytes[1]})
105
          .order(ByteOrder.BIG_ENDIAN)
106
          .getInt();
107
    } else {
108
      throw new IllegalArgumentException("Argument must be 2 bytes, was: " + bytes.length);
109
    }
110
  }
111
112
  /**
113
   * Read 4 bytes as a big endian unsigned 32-bit integer.
114
   *
115
   * <p>Result is of type <code>long</code> because Java doesn't have unsigned types.
116
   *
117
   * @return A value between 0 and 2^32 - 1, inclusive.
118
   */
119
  public static long getUint32(byte[] bytes) {
120 1 1. getUint32 : negated conditional → KILLED
    if (bytes.length == 4) {
121
      // Prepend zeroes so we can parse it as a signed int32 instead of a signed int16
122 1 1. getUint32 : replaced long return with 0 for com/yubico/internal/util/BinaryUtil::getUint32 → KILLED
      return ByteBuffer.wrap(new byte[] {0, 0, 0, 0, bytes[0], bytes[1], bytes[2], bytes[3]})
123
          .order(ByteOrder.BIG_ENDIAN)
124
          .getLong();
125
    } else {
126
      throw new IllegalArgumentException("Argument must be 4 bytes, was: " + bytes.length);
127
    }
128
  }
129
130
  public static byte[] encodeUint16(int value) {
131 3 1. encodeUint16 : removed call to com/yubico/internal/util/ExceptionUtil::assertTrue → KILLED
2. encodeUint16 : changed conditional boundary → KILLED
3. encodeUint16 : negated conditional → KILLED
    ExceptionUtil.assertTrue(value >= 0, "Argument must be non-negative, was: %d", value);
132 3 1. encodeUint16 : changed conditional boundary → SURVIVED
2. encodeUint16 : removed call to com/yubico/internal/util/ExceptionUtil::assertTrue → KILLED
3. encodeUint16 : negated conditional → KILLED
    ExceptionUtil.assertTrue(
133
        value < 65536, "Argument must be smaller than 2^16=65536, was: %d", value);
134
135
    ByteBuffer b = ByteBuffer.allocate(4);
136
    b.order(ByteOrder.BIG_ENDIAN);
137
    b.putInt(value);
138
    b.rewind();
139 1 1. encodeUint16 : replaced return value with null for com/yubico/internal/util/BinaryUtil::encodeUint16 → KILLED
    return Arrays.copyOfRange(b.array(), 2, 4);
140
  }
141
142
  public static byte[] encodeUint32(long value) {
143 3 1. encodeUint32 : removed call to com/yubico/internal/util/ExceptionUtil::assertTrue → NO_COVERAGE
2. encodeUint32 : negated conditional → NO_COVERAGE
3. encodeUint32 : changed conditional boundary → NO_COVERAGE
    ExceptionUtil.assertTrue(value >= 0, "Argument must be non-negative, was: %d", value);
144 3 1. encodeUint32 : removed call to com/yubico/internal/util/ExceptionUtil::assertTrue → NO_COVERAGE
2. encodeUint32 : negated conditional → NO_COVERAGE
3. encodeUint32 : changed conditional boundary → NO_COVERAGE
    ExceptionUtil.assertTrue(
145
        value < 4294967296L, "Argument must be smaller than 2^32=4294967296, was: %d", value);
146
147
    ByteBuffer b = ByteBuffer.allocate(8);
148
    b.order(ByteOrder.BIG_ENDIAN);
149
    b.putLong(value);
150
    b.rewind();
151 1 1. encodeUint32 : replaced return value with null for com/yubico/internal/util/BinaryUtil::encodeUint32 → NO_COVERAGE
    return Arrays.copyOfRange(b.array(), 4, 8);
152
  }
153
154
  public static byte[] readAll(InputStream is) throws IOException {
155
    byte[] buffer = new byte[1024];
156
    int bufferLen = 0;
157
    while (true) {
158 1 1. readAll : Replaced integer subtraction with addition → NO_COVERAGE
      final int moreLen = is.read(buffer, bufferLen, buffer.length - bufferLen);
159 2 1. readAll : changed conditional boundary → NO_COVERAGE
2. readAll : negated conditional → NO_COVERAGE
      if (moreLen <= 0) {
160 1 1. readAll : replaced return value with null for com/yubico/internal/util/BinaryUtil::readAll → NO_COVERAGE
        return Arrays.copyOf(buffer, bufferLen);
161
      } else {
162 1 1. readAll : Replaced integer addition with subtraction → NO_COVERAGE
        bufferLen += moreLen;
163 1 1. readAll : negated conditional → NO_COVERAGE
        if (bufferLen == buffer.length) {
164 1 1. readAll : Replaced integer multiplication with division → NO_COVERAGE
          buffer = Arrays.copyOf(buffer, buffer.length * 2);
165
        }
166
      }
167
    }
168
  }
169
}

Mutations

36

1.1
Location : copy
Killed by : none
replaced return value with null for com/yubico/internal/util/BinaryUtil::copy → NO_COVERAGE

43

1.1
Location : toHex
Killed by : com.yubico.internal.util.CertificateParserTest.subjectPublicKeyIdentifierIsCorrect(com.yubico.internal.util.CertificateParserTest)
Replaced integer multiplication with division → KILLED

44

1.1
Location : toHex
Killed by : com.yubico.internal.util.CertificateParserTest.subjectPublicKeyIdentifierIsCorrect(com.yubico.internal.util.CertificateParserTest)
negated conditional → KILLED

2.2
Location : toHex
Killed by : com.yubico.internal.util.CertificateParserTest.subjectPublicKeyIdentifierIsCorrect(com.yubico.internal.util.CertificateParserTest)
changed conditional boundary → KILLED

45

1.1
Location : toHex
Killed by : com.yubico.internal.util.CertificateParserTest.subjectPublicKeyIdentifierIsCorrect(com.yubico.internal.util.CertificateParserTest)
Replaced integer multiplication with division → KILLED

46

1.1
Location : toHex
Killed by : com.yubico.internal.util.CertificateParserTest.subjectPublicKeyIdentifierIsCorrect(com.yubico.internal.util.CertificateParserTest)
Replaced Shift Right with Shift Left → KILLED

2.2
Location : toHex
Killed by : com.yubico.internal.util.CertificateParserTest.subjectPublicKeyIdentifierIsCorrect(com.yubico.internal.util.CertificateParserTest)
Replaced bitwise AND with OR → KILLED

47

1.1
Location : toHex
Killed by : com.yubico.internal.util.CertificateParserTest.subjectPublicKeyIdentifierIsCorrect(com.yubico.internal.util.CertificateParserTest)
Replaced bitwise AND with OR → KILLED

2.2
Location : toHex
Killed by : com.yubico.internal.util.CertificateParserTest.subjectPublicKeyIdentifierIsCorrect(com.yubico.internal.util.CertificateParserTest)
Replaced integer addition with subtraction → KILLED

49

1.1
Location : toHex
Killed by : com.yubico.internal.util.CertificateParserTest.subjectPublicKeyIdentifierIsCorrect(com.yubico.internal.util.CertificateParserTest)
replaced return value with "" for com/yubico/internal/util/BinaryUtil::toHex → KILLED

56

1.1
Location : fromHex
Killed by : com.yubico.internal.util.BinaryUtilSpec
negated conditional → KILLED

2.2
Location : fromHex
Killed by : com.yubico.internal.util.BinaryUtilSpec
Replaced integer modulus with multiplication → KILLED

60

1.1
Location : fromHex
Killed by : com.yubico.internal.util.BinaryUtilSpec
Replaced integer division with multiplication → KILLED

61

1.1
Location : fromHex
Killed by : com.yubico.internal.util.BinaryUtilSpec
changed conditional boundary → KILLED

2.2
Location : fromHex
Killed by : com.yubico.internal.util.BinaryUtilSpec
negated conditional → KILLED

63

1.1
Location : fromHex
Killed by : com.yubico.internal.util.BinaryUtilSpec
changed conditional boundary → KILLED

2.2
Location : fromHex
Killed by : com.yubico.internal.util.BinaryUtilSpec
negated conditional → KILLED

66

1.1
Location : fromHex
Killed by : com.yubico.internal.util.BinaryUtilSpec
Replaced integer multiplication with division → KILLED

2.2
Location : fromHex
Killed by : com.yubico.internal.util.BinaryUtilSpec
Replaced integer addition with subtraction → KILLED

3.3
Location : fromHex
Killed by : com.yubico.internal.util.BinaryUtilSpec
Replaced Shift Left with Shift Right → KILLED

4.4
Location : fromHex
Killed by : com.yubico.internal.util.BinaryUtilSpec
Replaced bitwise OR with AND → KILLED

5.5
Location : fromHex
Killed by : com.yubico.internal.util.BinaryUtilSpec
Replaced integer modulus with multiplication → KILLED

6.6
Location : fromHex
Killed by : com.yubico.internal.util.BinaryUtilSpec
Replaced integer division with multiplication → KILLED

68

1.1
Location : fromHex
Killed by : com.yubico.internal.util.BinaryUtilSpec
replaced return value with null for com/yubico/internal/util/BinaryUtil::fromHex → KILLED

77

1.1
Location : singleFromHex
Killed by : none
removed call to com/yubico/internal/util/ExceptionUtil::assertTrue → NO_COVERAGE

78

1.1
Location : singleFromHex
Killed by : none
negated conditional → NO_COVERAGE

79

1.1
Location : singleFromHex
Killed by : none
replaced byte return with 0 for com/yubico/internal/util/BinaryUtil::singleFromHex → NO_COVERAGE

91

1.1
Location : getUint8
Killed by : com.yubico.internal.util.BinaryUtilSpec
replaced short return with 0 for com/yubico/internal/util/BinaryUtil::getUint8 → KILLED

102

1.1
Location : getUint16
Killed by : com.yubico.internal.util.BinaryUtilSpec
negated conditional → KILLED

104

1.1
Location : getUint16
Killed by : com.yubico.internal.util.BinaryUtilSpec
replaced int return with 0 for com/yubico/internal/util/BinaryUtil::getUint16 → KILLED

120

1.1
Location : getUint32
Killed by : com.yubico.internal.util.BinaryUtilSpec
negated conditional → KILLED

122

1.1
Location : getUint32
Killed by : com.yubico.internal.util.BinaryUtilSpec
replaced long return with 0 for com/yubico/internal/util/BinaryUtil::getUint32 → KILLED

131

1.1
Location : encodeUint16
Killed by : com.yubico.internal.util.BinaryUtilSpec
removed call to com/yubico/internal/util/ExceptionUtil::assertTrue → KILLED

2.2
Location : encodeUint16
Killed by : com.yubico.internal.util.BinaryUtilSpec
changed conditional boundary → KILLED

3.3
Location : encodeUint16
Killed by : com.yubico.internal.util.BinaryUtilSpec
negated conditional → KILLED

132

1.1
Location : encodeUint16
Killed by : com.yubico.internal.util.BinaryUtilSpec
removed call to com/yubico/internal/util/ExceptionUtil::assertTrue → KILLED

2.2
Location : encodeUint16
Killed by : none
changed conditional boundary → SURVIVED

3.3
Location : encodeUint16
Killed by : com.yubico.internal.util.BinaryUtilSpec
negated conditional → KILLED

139

1.1
Location : encodeUint16
Killed by : com.yubico.internal.util.BinaryUtilSpec
replaced return value with null for com/yubico/internal/util/BinaryUtil::encodeUint16 → KILLED

143

1.1
Location : encodeUint32
Killed by : none
removed call to com/yubico/internal/util/ExceptionUtil::assertTrue → NO_COVERAGE

2.2
Location : encodeUint32
Killed by : none
negated conditional → NO_COVERAGE

3.3
Location : encodeUint32
Killed by : none
changed conditional boundary → NO_COVERAGE

144

1.1
Location : encodeUint32
Killed by : none
removed call to com/yubico/internal/util/ExceptionUtil::assertTrue → NO_COVERAGE

2.2
Location : encodeUint32
Killed by : none
negated conditional → NO_COVERAGE

3.3
Location : encodeUint32
Killed by : none
changed conditional boundary → NO_COVERAGE

151

1.1
Location : encodeUint32
Killed by : none
replaced return value with null for com/yubico/internal/util/BinaryUtil::encodeUint32 → NO_COVERAGE

158

1.1
Location : readAll
Killed by : none
Replaced integer subtraction with addition → NO_COVERAGE

159

1.1
Location : readAll
Killed by : none
changed conditional boundary → NO_COVERAGE

2.2
Location : readAll
Killed by : none
negated conditional → NO_COVERAGE

160

1.1
Location : readAll
Killed by : none
replaced return value with null for com/yubico/internal/util/BinaryUtil::readAll → NO_COVERAGE

162

1.1
Location : readAll
Killed by : none
Replaced integer addition with subtraction → NO_COVERAGE

163

1.1
Location : readAll
Killed by : none
negated conditional → NO_COVERAGE

164

1.1
Location : readAll
Killed by : none
Replaced integer multiplication with division → NO_COVERAGE

Active mutators

Tests examined


Report generated by PIT 1.15.0