bogue : limite de taille des mod?les

Bonjour,

en SPIP 1.9.1 (je n'ai pas testé en 1.9.2), j'ai constaté que le texte
engendré par un modèle ne peut pas dépasser 25000 caractères environ.
Au-delà, il n'est tout simplement pas affiché.

J'ai fini par trouver l'origine du problème : dans la fonction
extraire_attribut (fichier ecrire/inc/filtres.php) on trouve :
  if (preg_match(
        ',(.*?<[^>]*)(\s'.$attribut.'=\s*([\'"]?)([^\\3]*?)\\3)([^>]*>.*),isS',
        $balise, $r)) {

Or la fonction preg_match ne peut pas rechercher dans une chaine très
longue un motif "non gourmand" (non greedy) tel que ".*?" ou
"([^\\3]*?)" ; la doc de pcre indique que ces motifs sont traités
récursivement, d'où une limite liée à la taille de la pile de
récursion.

En général, la $balise passée à extraire_attribut est très loin
d'atteindre cette limite, mais lors de l'affichage d'un modèle, on lui
passe une balise qui contient en fait tout le texte engendré par le
modèle (encodé en base64), ce qui coince si ce texte est long.

Ce problème a-t-il déjà été signalé ? Y a-t-il une solution connue ?
Il ne serait pas difficile de récrire ce motif sans utiliser de
construction "non gourmande", mais je crains d'introduire des effets
indésirables ailleurs, cette fonction étant utilisée à beaucoup
d'endroits dans le code.

J'apprécierais un avis ou conseil sur la façon de s'en sortir
"proprement" sans trop de bidouillage :slight_smile:

Merci,
Nicolas

Quel modèle utilises tu ?

-----Message d'origine-----
De : spip-bounces@rezo.net [mailto:spip-bounces@rezo.net] De la part de
spip@graner.name
Envoyé : dimanche 17 février 2008 13:10
À : spip@rezo.net
Objet : [Spip] bogue : limite de taille des mod?les

Bonjour,

en SPIP 1.9.1 (je n'ai pas testé en 1.9.2), j'ai constaté que le texte
engendré par un modèle ne peut pas dépasser 25000 caractères environ.
Au-delà, il n'est tout simplement pas affiché.

J'ai fini par trouver l'origine du problème : dans la fonction
extraire_attribut (fichier ecrire/inc/filtres.php) on trouve :
  if (preg_match(

',(.*?<[^>]*)(\s'.$attribut.'=\s*([\'"]?)([^\\3]*?)\\3)([^>]*>.*),isS',
        $balise, $r)) {

Or la fonction preg_match ne peut pas rechercher dans une chaine très
longue un motif "non gourmand" (non greedy) tel que ".*?" ou
"([^\\3]*?)" ; la doc de pcre indique que ces motifs sont traités
récursivement, d'où une limite liée à la taille de la pile de
récursion.

En général, la $balise passée à extraire_attribut est très loin
d'atteindre cette limite, mais lors de l'affichage d'un modèle, on lui
passe une balise qui contient en fait tout le texte engendré par le
modèle (encodé en base64), ce qui coince si ce texte est long.

Ce problème a-t-il déjà été signalé ? Y a-t-il une solution connue ?
Il ne serait pas difficile de récrire ce motif sans utiliser de
construction "non gourmande", mais je crains d'introduire des effets
indésirables ailleurs, cette fonction étant utilisée à beaucoup
d'endroits dans le code.

J'apprécierais un avis ou conseil sur la façon de s'en sortir
"proprement" sans trop de bidouillage :slight_smile:

Merci,
Nicolas

_______________________________________________
liste spip
spip@rezo.net - désabonnement : spip-off@rezo.net
Infos et archives : http://listes.rezo.net/mailman/listinfo/spip
Documentation de SPIP : http://www.spip.net/
irc://irc.freenode.net/spip
FAQ : http://www.spip.net/fr_article1054.html

J'utilise un modèle fait maison. Mon but est qu'une partie du texte de
ma page soit calculée par un script PHP, le reste étant géré
normalement dans l'espace privé. On peut le faire avec un squelette
spécifique (c'est ce que je fais pour le moment, à cause du bogue en
question) mais c'est vachement plus simple avec un modèle.

Le problème ne vient pas du modèle lui-même mais bien de la longueur
du texte qu'il engendre. Par exemple, si dans
squelettes/modeles/toto.html je mets une ligne :

<? echo str_repeat("a", 24900) ?>

et dans ma page je mets <toto1>, il s'affiche bien une longue ligne de
"aaa....". Mais si je change juste le nombre :

<? echo str_repeat("a", 25000) ?>

il ne s'affiche plus rien (ce n'est pas un problème d'affichage, il
n'y a rien dans le source HTML de la page à cet endroit-là).

La limite vient bien de preg_match (appelé dans la fonction
extraire_attribut) et pas de SPIP, on peut s'en apercevoir par exemple
en mettant le script PHP suivant tout seul dans une page,
indépendamment de SPIP :

<?
$x = str_repeat("a",99997) ;
echo preg_match("/^a*$/", $x) ? "oui " : "non " ;
echo preg_match("/^a*?$/", $x) ? "oui " : "non " ;
$x = str_repeat("a",99998) ;
echo preg_match("/^a*$/", $x) ? "oui " : "non " ;
echo preg_match("/^a*?$/", $x) ? "oui " : "non " ;
?>

Ce script affiche "oui oui oui non" sur différentes versions de PHP où
je l'ai testé, alors que normalement il devrait afficher "oui oui oui
oui" (il se peut que le nombre exact qui fait apparaître "non" à la
place de "oui" varie selon les serveurs). Ceci confirme que preg_match
ne trouve pas les motifs utilisant "*?" dans des chaines trop longues,
ce qui est à la source de mon problème.

Il ne s'agit donc pas de corriger un bogue dans mon modèle ni dans
SPIP, mais de contourner un bogue de PHP (ou plutôt une limitation)
qui a des répercussions dans SPIP. Pour cela il faudrait modifier le
motif utilisé dans extraire_attribut pour éviter les "*?".

Nicolas

From: "Samy RABIH" <samy.rabih@free.fr>
Date: Sun, 17 Feb 2008 13:34:59 +0100

Quel modèle utilises tu ?

-----Message d'origine-----
De : spip-bounces@rezo.net [mailto:spip-bounces@rezo.net] De la part de
spip@graner.name
Envoyé : dimanche 17 février 2008 13:10
À : spip@rezo.net
Objet : [Spip] bogue : limite de taille des mod?les

Bonjour,

en SPIP 1.9.1 (je n'ai pas testé en 1.9.2), j'ai constaté que le texte
engendré par un modèle ne peut pas dépasser 25000 caractères environ.
Au-delà, il n'est tout simplement pas affiché.

J'ai fini par trouver l'origine du problème : dans la fonction
extraire_attribut (fichier ecrire/inc/filtres.php) on trouve :
  if (preg_match(

',(.*?<[^>]*)(\s'.$attribut.'=\s*([\'"]?)([^\\3]*?)\\3)([^>]*>.*),isS',
        $balise, $r)) {

Or la fonction preg_match ne peut pas rechercher dans une chaine très
longue un motif "non gourmand" (non greedy) tel que ".*?" ou
"([^\\3]*?)" ; la doc de pcre indique que ces motifs sont traités
récursivement, d'où une limite liée à la taille de la pile de
récursion.

En général, la $balise passée à extraire_attribut est très loin
d'atteindre cette limite, mais lors de l'affichage d'un modèle, on lui
passe une balise qui contient en fait tout le texte engendré par le
modèle (encodé en base64), ce qui coince si ce texte est long.

Ce problème a-t-il déjà été signalé ? Y a-t-il une solution connue ?
Il ne serait pas difficile de récrire ce motif sans utiliser de
construction "non gourmande", mais je crains d'introduire des effets
indésirables ailleurs, cette fonction étant utilisée à beaucoup
d'endroits dans le code.

J'apprécierais un avis ou conseil sur la façon de s'en sortir
"proprement" sans trop de bidouillage :slight_smile:

Merci,
Nicolas