@@ -1,5 +1,5 @@
/*
* Copyright (c) 2014, 2017 , Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2014, 2021 , Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -59,41 +59,26 @@ ImageStrings getStrings() {
return strings ;
}
static long [] decompress (ByteBuffer bytes ) {
static long [] decompress (ByteBuffer bytes , int offset ) {
Objects .requireNonNull (bytes );
long [] attributes = new long [ATTRIBUTE_COUNT ];
if (bytes != null ) {
while (bytes .hasRemaining ()) {
int data = bytes .get () & 0xFF ;
int kind = data >>> 3 ;
if (kind == ATTRIBUTE_END ) {
break ;
}
if (kind < ATTRIBUTE_END || ATTRIBUTE_COUNT <= kind ) {
throw new InternalError (
"Invalid jimage attribute kind: " + kind );
}
int length = (data & 0x7 ) + 1 ;
long value = 0 ;
for (int j = 0 ; j < length ; j ++) {
value <<= 8 ;
if (!bytes .hasRemaining ()) {
throw new InternalError ("Missing jimage attribute data" );
}
value |= bytes .get () & 0xFF ;
}
attributes [kind ] = value ;
int limit = bytes .limit ();
while (offset < limit ) {
int data = bytes .get (offset ++) & 0xFF ;
if (data <= 0x7 ) { // ATTRIBUTE_END
break ;
}
int kind = data >>> 3 ;
if (ATTRIBUTE_COUNT <= kind ) {
throw new InternalError (
"Invalid jimage attribute kind: " + kind );
}
}
int length = (data & 0x7 ) + 1 ;
attributes [kind ] = readValue (length , bytes , offset , limit );
offset += length ;
}
return attributes ;
}
@@ -126,71 +111,125 @@ public boolean verify(String name) {
/**
* A simpler verification would be {@code name.equals(getFullName())}, but
* by not creating the full name and enabling early returns we allocate
* fewer objects. Could possibly be made allocation free by extending
* ImageStrings to test if strings at an offset match the name region.
* fewer objects.
*/
static boolean verify (String name , long [] attributes , ImageStrings strings ) {
Objects .requireNonNull (name );
final int length = name .length ();
int index = 0 ;
int moduleOffset = (int )attributes [ATTRIBUTE_MODULE ];
if (moduleOffset != 0 ) {
String module = strings .get (moduleOffset );
final int moduleLen = module .length ();
if (moduleOffset != 0 && length >= 1 ) {
int moduleLen = strings .match (moduleOffset , name , 1 );
index = moduleLen + 1 ;
if (length <= index
if (moduleLen < 0
|| length <= index
|| name .charAt (0 ) != '/'
|| !name .regionMatches (1 , module , 0 , moduleLen )
|| name .charAt (index ++) != '/' ) {
return false ;
}
}
return verifyName (null , name , index , length , 0 ,
(int ) attributes [ATTRIBUTE_PARENT ],
(int ) attributes [ATTRIBUTE_BASE ],
(int ) attributes [ATTRIBUTE_EXTENSION ],
strings );
}
return verifyName (name , index , length , attributes , strings );
static boolean verify (String module , String name , ByteBuffer locations ,
int locationOffset , ImageStrings strings ) {
int moduleOffset = 0 ;
int parentOffset = 0 ;
int baseOffset = 0 ;
int extOffset = 0 ;
int limit = locations .limit ();
while (locationOffset < limit ) {
int data = locations .get (locationOffset ++) & 0xFF ;
if (data <= 0x7 ) { // ATTRIBUTE_END
break ;
}
int kind = data >>> 3 ;
if (ATTRIBUTE_COUNT <= kind ) {
throw new InternalError (
"Invalid jimage attribute kind: " + kind );
}
int length = (data & 0x7 ) + 1 ;
switch (kind ) {
case ATTRIBUTE_MODULE :
moduleOffset = (int ) readValue (length , locations , locationOffset , limit );
break ;
case ATTRIBUTE_BASE :
baseOffset = (int ) readValue (length , locations , locationOffset , limit );
break ;
case ATTRIBUTE_PARENT :
parentOffset = (int ) readValue (length , locations , locationOffset , limit );
break ;
case ATTRIBUTE_EXTENSION :
extOffset = (int ) readValue (length , locations , locationOffset , limit );
break ;
}
locationOffset += length ;
}
return verifyName (module , name , 0 , name .length (),
moduleOffset , parentOffset , baseOffset , extOffset , strings );
}
private static long readValue (int length , ByteBuffer buffer , int offset , int limit ) {
long value = 0 ;
for (int j = 0 ; j < length ; j ++) {
value <<= 8 ;
if (offset >= limit ) {
throw new InternalError ("Missing jimage attribute data" );
}
value |= buffer .get (offset ++) & 0xFF ;
}
return value ;
}
static boolean verify (String module , String name , long [] attributes ,
ImageStrings strings ) {
Objects .requireNonNull (module );
Objects .requireNonNull (name );
int moduleOffset = (int )attributes [ATTRIBUTE_MODULE ];
return verifyName (module , name , 0 , name .length (),
(int ) attributes [ATTRIBUTE_MODULE ],
(int ) attributes [ATTRIBUTE_PARENT ],
(int ) attributes [ATTRIBUTE_BASE ],
(int ) attributes [ATTRIBUTE_EXTENSION ],
strings );
}
private static boolean verifyName (String module , String name , int index , int length ,
int moduleOffset , int parentOffset , int baseOffset , int extOffset , ImageStrings strings ) {
if (moduleOffset != 0 ) {
if (! module . equals ( strings .get (moduleOffset ) )) {
if (strings .match (moduleOffset , module , 0 ) != module . length ( )) {
return false ;
}
}
return verifyName (name , 0 , name .length (), attributes , strings );
}
private static boolean verifyName (String name , int index , int length ,
long [] attributes , ImageStrings strings ) {
int parentOffset = (int ) attributes [ATTRIBUTE_PARENT ];
if (parentOffset != 0 ) {
String parent = strings .get (parentOffset );
final int parentLen = parent .length ();
if (!name .regionMatches (index , parent , 0 , parentLen )) {
int parentLen = strings .match (parentOffset , name , index );
if (parentLen < 0 ) {
return false ;
}
index += parentLen ;
if (length <= index || name .charAt (index ++) != '/' ) {
return false ;
}
}
String base = strings .get ((int ) attributes [ATTRIBUTE_BASE ]);
final int baseLen = base .length ();
if (!name .regionMatches (index , base , 0 , baseLen )) {
int baseLen = strings .match (baseOffset , name , index );
if (baseLen < 0 ) {
return false ;
}
index += baseLen ;
int extOffset = (int ) attributes [ATTRIBUTE_EXTENSION ];
if (extOffset != 0 ) {
String extension = strings .get (extOffset );
int extLen = extension .length ();
if (length <= index
|| name .charAt (index ++) != '.'
|| !name .regionMatches (index , extension , 0 , extLen )) {
|| name .charAt (index ++) != '.' ) {
return false ;
}
int extLen = strings .match (extOffset , name , index );
if (extLen < 0 ) {
return false ;
}
index += extLen ;
@@ -203,7 +242,6 @@ long getAttribute(int kind) {
throw new InternalError (
"Invalid jimage attribute kind: " + kind );
}
return attributes [kind ];
}
@@ -212,7 +250,6 @@ String getAttributeString(int kind) {
throw new InternalError (
"Invalid jimage attribute kind: " + kind );
}
return getStrings ().get ((int )attributes [kind ]);
}