3333use function preg_replace ;
3434use function round ;
3535use function sprintf ;
36+ use function strlen ;
3637use function substr ;
3738use function unpack ;
3839use const PHP_INT_MAX ;
3940
4041class Binary{
42+ public const SIZEOF_BYTE = 1 ;
43+ public const SIZEOF_SHORT = 2 ;
44+ public const SIZEOF_INT = 4 ;
45+ public const SIZEOF_LONG = 8 ;
46+
47+ public const SIZEOF_FLOAT = 4 ;
48+ public const SIZEOF_DOUBLE = 8 ;
49+
4150 public static function signByte (int $ value ) : int {
4251 return $ value << 56 >> 56 ;
4352 }
@@ -76,13 +85,18 @@ public static function flipLongEndianness(int $value) : int{
7685
7786 /**
7887 * @return mixed[]
88+ * @throws BinaryDataException
7989 */
80- private static function safeUnpack (string $ formatCode , string $ bytes ) : array {
90+ private static function safeUnpack (string $ formatCode , string $ bytes , int $ needLength ) : array {
91+ $ haveLength = strlen ($ bytes );
92+ if ($ haveLength < $ needLength ){
93+ throw new BinaryDataException ("Not enough bytes: need $ needLength, have $ haveLength " );
94+ }
8195 //unpack SUCKS SO BADLY. We really need an extension to replace this garbage :(
8296 $ result = unpack ($ formatCode , $ bytes );
8397 if ($ result === false ){
84- //assume the formatting code is valid, since we provided it
85- throw new BinaryDataException ( " Invalid input data (not enough?) " );
98+ //this should never happen; we checked the length above
99+ throw new \ AssertionError ( " unpack() failed for unknown reason " );
86100 }
87101 return $ result ;
88102 }
@@ -136,14 +150,14 @@ public static function writeByte(int $c) : string{
136150 * Reads a 16-bit unsigned big-endian number
137151 */
138152 public static function readShort (string $ str ) : int {
139- return self ::safeUnpack ("n " , $ str )[1 ];
153+ return self ::safeUnpack ("n " , $ str, self :: SIZEOF_SHORT )[1 ];
140154 }
141155
142156 /**
143157 * Reads a 16-bit signed big-endian number
144158 */
145159 public static function readSignedShort (string $ str ) : int {
146- return self ::signShort (self ::safeUnpack ("n " , $ str )[1 ]);
160+ return self ::signShort (self ::safeUnpack ("n " , $ str, self :: SIZEOF_SHORT )[1 ]);
147161 }
148162
149163 /**
@@ -157,14 +171,14 @@ public static function writeShort(int $value) : string{
157171 * Reads a 16-bit unsigned little-endian number
158172 */
159173 public static function readLShort (string $ str ) : int {
160- return self ::safeUnpack ("v " , $ str )[1 ];
174+ return self ::safeUnpack ("v " , $ str, self :: SIZEOF_SHORT )[1 ];
161175 }
162176
163177 /**
164178 * Reads a 16-bit signed little-endian number
165179 */
166180 public static function readSignedLShort (string $ str ) : int {
167- return self ::signShort (self ::safeUnpack ("v " , $ str )[1 ]);
181+ return self ::signShort (self ::safeUnpack ("v " , $ str, self :: SIZEOF_SHORT )[1 ]);
168182 }
169183
170184 /**
@@ -178,7 +192,7 @@ public static function writeLShort(int $value) : string{
178192 * Reads a 3-byte big-endian number
179193 */
180194 public static function readTriad (string $ str ) : int {
181- return self ::safeUnpack ("N " , "\x00" . $ str )[1 ];
195+ return self ::safeUnpack ("N " , "\x00" . $ str, self :: SIZEOF_INT )[1 ];
182196 }
183197
184198 /**
@@ -192,7 +206,7 @@ public static function writeTriad(int $value) : string{
192206 * Reads a 3-byte little-endian number
193207 */
194208 public static function readLTriad (string $ str ) : int {
195- return self ::safeUnpack ("V " , $ str . "\x00" )[1 ];
209+ return self ::safeUnpack ("V " , $ str . "\x00" , self :: SIZEOF_INT )[1 ];
196210 }
197211
198212 /**
@@ -206,7 +220,7 @@ public static function writeLTriad(int $value) : string{
206220 * Reads a 4-byte signed integer
207221 */
208222 public static function readInt (string $ str ) : int {
209- return self ::signInt (self ::safeUnpack ("N " , $ str )[1 ]);
223+ return self ::signInt (self ::safeUnpack ("N " , $ str, self :: SIZEOF_INT )[1 ]);
210224 }
211225
212226 /**
@@ -220,7 +234,7 @@ public static function writeInt(int $value) : string{
220234 * Reads a 4-byte signed little-endian integer
221235 */
222236 public static function readLInt (string $ str ) : int {
223- return self ::signInt (self ::safeUnpack ("V " , $ str )[1 ]);
237+ return self ::signInt (self ::safeUnpack ("V " , $ str, self :: SIZEOF_INT )[1 ]);
224238 }
225239
226240 /**
@@ -234,7 +248,7 @@ public static function writeLInt(int $value) : string{
234248 * Reads a 4-byte floating-point number
235249 */
236250 public static function readFloat (string $ str ) : float {
237- return self ::safeUnpack ("G " , $ str )[1 ];
251+ return self ::safeUnpack ("G " , $ str, self :: SIZEOF_FLOAT )[1 ];
238252 }
239253
240254 /**
@@ -255,7 +269,7 @@ public static function writeFloat(float $value) : string{
255269 * Reads a 4-byte little-endian floating-point number.
256270 */
257271 public static function readLFloat (string $ str ) : float {
258- return self ::safeUnpack ("g " , $ str )[1 ];
272+ return self ::safeUnpack ("g " , $ str, self :: SIZEOF_FLOAT )[1 ];
259273 }
260274
261275 /**
@@ -283,7 +297,7 @@ public static function printFloat(float $value) : string{
283297 * Reads an 8-byte floating-point number.
284298 */
285299 public static function readDouble (string $ str ) : float {
286- return self ::safeUnpack ("E " , $ str )[1 ];
300+ return self ::safeUnpack ("E " , $ str, self :: SIZEOF_DOUBLE )[1 ];
287301 }
288302
289303 /**
@@ -297,7 +311,7 @@ public static function writeDouble(float $value) : string{
297311 * Reads an 8-byte little-endian floating-point number.
298312 */
299313 public static function readLDouble (string $ str ) : float {
300- return self ::safeUnpack ("e " , $ str )[1 ];
314+ return self ::safeUnpack ("e " , $ str, self :: SIZEOF_DOUBLE )[1 ];
301315 }
302316
303317 /**
@@ -311,7 +325,7 @@ public static function writeLDouble(float $value) : string{
311325 * Reads an 8-byte integer.
312326 */
313327 public static function readLong (string $ str ) : int {
314- return self ::safeUnpack ("J " , $ str )[1 ];
328+ return self ::safeUnpack ("J " , $ str, self :: SIZEOF_LONG )[1 ];
315329 }
316330
317331 /**
@@ -325,7 +339,7 @@ public static function writeLong(int $value) : string{
325339 * Reads an 8-byte little-endian integer.
326340 */
327341 public static function readLLong (string $ str ) : int {
328- return self ::safeUnpack ("P " , $ str )[1 ];
342+ return self ::safeUnpack ("P " , $ str, self :: SIZEOF_LONG )[1 ];
329343 }
330344
331345 /**
0 commit comments