La question a reçu une bonne réponse par @mhaller. Je dirais que le soi-disant-puzzle a été assez facile et simplement en regardant la disposition des c-teurs de la Chaîne, on devrait être en mesure de trouver le comment de la partie, un
Procédure pas à pas
C-tor d'intérêt est ci-dessous, si vous êtes à la break-in/fissure/recherche de vulnérabilité de la sécurité, toujours regarder pour les non-final arbitraire des classes. Le cas ici est - java.nio.charset.Charset
//String
public String(byte bytes[], int offset, int length, Charset charset) {
if (charset == null)
throw new NullPointerException("charset");
checkBounds(bytes, offset, length);
char[] v = StringCoding.decode(charset, bytes, offset, length);
this.offset = 0;
this.count = v.length;
this.value = v;
}
Le c-tor propose soi-disant-moyen rapide de convertir byte[]
à la Chaîne en passant par le Charset pas le chartset nom pour éviter la recherche de chartsetName->jeu de caractères.
Il permet également de passer l'arbitraire d'un jeu de caractères de l'objet pour créer des chaînes. Jeu de caractères de routage principal convertit le contenu de java.nio.ByteBuffer
de CharBuffer
. Le CharBuffer peut contenir une référence à char[] et il est disponible via array()
, aussi la CharBuffer est entièrement modifiable.
//StringCoding
static char[] decode(Charset cs, byte[] ba, int off, int len) {
StringDecoder sd = new StringDecoder(cs, cs.name());
Afin d'éviter d'altérer l' byte[] b = Arrays.copyOf(ba, ba.length);
les développeurs java copier le tableau comme n'importe quelle autre Chaîne de construction (par exemple,
return sd.decode(b, off, len);
}
//StringDecoder
char[] decode(byte[] ba, int off, int len) {
int en = scale(len, cd.maxCharsPerByte());
char[] ca = new char[en];
if (len == 0)
return ca;
cd.reset();
). Il existe toutefois une exception: si aucun SecurityManager est installé, le char[] n'est pas copié.
ByteBuffer bb = ByteBuffer.wrap(ba, off, len);
Donc, si il n'y a pas de SecurityManager il est tout à fait possible d'avoir une modifiables CharBuffer/char[] qui est référencé par une Chaîne.
Tout semble parfait maintenant - à l'exception de l'
CharBuffer cb = CharBuffer.wrap(ca);
try {
CoderResult cr = cd.decode(bb, cb, true);
if (!cr.isUnderflow())
cr.throwException();
cr = cd.flush(cb);
if (!cr.isUnderflow())
cr.throwException();
} catch (CharacterCodingException x) {
// Substitution is always enabled,
// so this shouldn't happen
throw new Error(x);
}
return safeTrim(ca, cb.position(), cs);
}
est également copié (les caractères gras ci-dessus). C'est
où les développeurs java est allé paresseux et massivement mal.
La copie est nécessaire pour empêcher le voleur jeu de caractères (exemple ci-dessus) pour être en mesure de modifier la source de byte[]. Cependant, imaginez le cas d'avoir autour de 512KO char[]
de la mémoire tampon qui contient peu de Chaîne. La tentative de créer un seul petit, quelques graphiques - public String(char value[])
énorme avec 512KO byte[] copie. Si la mémoire tampon ont été de 1 ko ou alors, l'impact ne sera jamais vraiment remarqué. Avec des tampons de grande taille, le gain de performance est vraiment énorme, cependant. La seule solution serait de copier la partie pertinente.
...ou bien les concepteurs de l'
//Trim the given char array to the given length
//
private static char[] safeTrim(char[] ca, int len, Charset cs) {
if (len == ca.length
&& (System.getSecurityManager() == null
|| cs.getClass().getClassLoader0() == null))
return ca;
else
return Arrays.copyOf(ca, len);
}
pensé par l'introduction en lecture seule Tampons. Simplement en appelant
byte[]
aurait été suffisant (si le jeu de caractères.getClassLoader()!=null)*
Parfois, même les gars qui travaillent sur
byte[]
pouvez l'obtenir tout à fait tort.
*Classe.getClassLoader() renvoie la valeur null pour les classes de bootstrap, c'est à dire ceux à venir avec la JVM elle-même.