Chaîne d'échappement dans un contexte d'évaluation avec JSON.stringify

Nov 13 2020

Tout d'abord: je sais qu'il y a beaucoup de questions liées à la fuite, mais je n'ai pas trouvé de réponse généralement valable jusqu'à présent. Disons que j'ai cette fonction de jouet simple pour la démonstration:

function f(somePOJO) {
  var s = eval("'" + JSON.stringify(somePOJO) + "';"); // for demonstration only
  return JSON.parse(s);
}
const clone = f({a: 1, b: "c"});

Étant donné un objet littéral tel que {a: 1, b: "c"}(un POJO), fdevrait en renvoyer un "clone". (Notez que je n'utilise pas vraiment cette approche pour le clonage ou similaire, et je suis conscient que evalc'est mal et aussi que ce n'est même pas nécessaire ici, c'est juste pour la démonstration du problème de fuite!)

Cela fonctionne bien, mais seulement tant que les valeurs POJO ne contiennent pas de fichier '. Maintenant, bien sûr, je pourrais échapper au JSON en utilisant quelque chose comme JSON.stringify(somePOJO).replace(/'/g, "\\'"). Cela fonctionne si les valeurs POJO contiennent ', mais pas si elles contiennent \\'. Et cela crée une spirale d'évasion ...

Y a-t-il une solution à cela?

Réponses

1 traktor Nov 13 2020 at 14:01

La fonction d'échappement pour conserver une chaîne JSON en étant évaluée par la evalfonction, le compilateur JavaScript dans certaines circonstances ou par la JSON.parsefonction est en fait JSON.stringify. Cette JSONméthode enchaînera volontiers les valeurs de chaîne, pas seulement les types de données d'objet.

function f(somePOJO) {
  var s = eval( JSON.stringify(JSON.stringify(somePOJO)) );
  return JSON.parse(s);
}
const obj = {a: 1, b: "c", d: "back\\, forward/"}
const clone = f(obj);
console.log(obj);
console.log(clone);

La raison pour laquelle il ne fait pas partie de la escape/encodeURI/encodeURIComponentfamille de fonctions est qu'il s'agit de caractères d'échappement à inclure dans les URL, alors que ce cas concerne les caractères d'échappement à analyser par un analyseur JavaScipt.

Dans la plupart des cas, en particulier pour analyser du texte JSON à l'aide JSON.parse, il n'est tout simplement pas nécessaire de stringifier le texte JSON une deuxième fois et de l'analyser deux fois.

D'un intérêt quelque peu académique maintenant, mais avant l'introduction de JSONen Javascript, on pouvait stringifier une chaîne en inspectant en série ses caractères et les barres obliques inverses échappant les barres obliques inverses, au moins un type de guillemets et les codes de contrôle d'échappement Unicode - la question postée peut manquer la partie à propos de la nécessité d'échapper les caractères anti-slash ainsi que les guillemets.