LuaSandbox/fr
Pour l'extension MediaWiki qui permet l'utilisation du code Lua dans le bac à sable voir Extension:Scribunto
LuaSandbox est une extension pour PHP 7 et PHP 8 qui permet d'exécuter sous PHP et de manière sécurisée du code Lua 5.1; c'est généralement plus rapide que de passer par le shell avec un binaire Lua et la communication inter-processus.
Installation
Pré-empaquetage
Distributions basées sur Apt (Debian, Ubuntu, etc.)
LuaSandbox est disponible sous Debian 10 et Ubuntu 18.04 ou plus récents. Installation à l'aide de la commande suivante :
apt install php-luasandbox -y
Distributions basées sur RPM (Fedora/RedHat, SUSE, etc.)
LuaSandbox peut être installé depuis le dépôt REMI. La liste des RPM disponibles est disponible ici.
PECL
LuaSandbox est maintenant disponible en PECL, qui fournit également des DLL Windows préconstruites. Voir notre page du package. Installez d'abord la bibliothèque Lua 5.1 correctement comme indiqué ci-dessous dans installation manuelle. Puis exécutez :
pecl install luasandbox
Installation manuelle
Prérequis
Installer les fichiers d'entête et les bibliothèques pour PHP et Lua 5.1.
- Pour les distributions Linux dérivées de Debian, telles que Ubuntu :
apt install php-dev liblua5.1-0-dev -y
- Pour les distributions Linux dérivées de CentOS/Redhat :
yum install php-devel lua5.1 lua5.1-devel
- Pour macOS
brew install lua
Téléchargement
Télécharger le code source dans un répertoire approprié à partir de Git :
git init
git pull https://gerrit.wikimedia.org/r/mediawiki/php/luasandbox.git
Ou téléchargez une image et développez-la.
Construction
luasandbox
est le répertoire dans lequel le répertoire Git de LuaSandbox a été copié.
cd luasandbox
phpize && ./configure && make && sudo make install
Puis ajoutez extension=luasandbox.so
dans la configuration PHP à un endroit approprié.
Par exemple, dans les distributions dérivées modernes de Debian, vous ajouterez un fichier à /etc/php/$version/mods-available
(où $version
est la version de PHP pour laquelle vous avez choisi LuaSandbox) et utiliserez la commande phpenmod
pour l'activer.
Si vous utilisez LuaSandbox avec une application web comme MediaWiki, vous devrez redémarrer votre serveur web ou php-fpm
pour PHP afin de charger l'extension.
Après ce rechargement, vous devriez voir LuaSandbox dans la sortie phpinfo()
et get_loaded_extensions()
(et, pour MediaWiki avec Scribunto installé, dans Special:Version).
Exemples
$sandbox = new LuaSandbox;
$sandbox->setMemoryLimit( 50 * 1024 * 1024 );
$sandbox->setCPULimit( 10 );
// Enregistrer quelques fonctions dans l'environnement Lua
function frobnosticate( $v ) {
return [ $v + 42 ];
}
$sandbox->registerLibrary( 'php', [
'frobnosticate' => 'frobnosticate',
'output' => function ( $string ) {
echo "$string\n";
},
'error' => function () {
throw new LuaSandboxRuntimeError( "Quelque chose ne va pas" );
}
] );
// Exécuter du code Lua comprenant des procédures de rappel dans PHP mais également dans Lua.
$luaCode = <<<EOF
php.output( "Hello, world" );
return "Hi", function ( v )
return php.frobnosticate( v + 200 )
end
EOF;
list( $hi, $frob ) = $sandbox->loadString( $luaCode )->call();
assert( $frob->call( 4000 ) === [ 4242 ] );
// Les exceptions LuaSandboxRuntimeError peuvent être récupérées par Lua
list( $ok, $message ) = $sandbox->loadString( 'return pcall( php.error )' )->call();
assert( !$ok );
assert( $message === 'Something is wrong' );
Documentation
Notre documentation se trouve maintenant en amont, dans le manuel PHP sur https://www.php.net/book.luasandbox.
Si vous souhaitez modifier le manuel, vous pouvez soit soumettre une demande de tirage (pull) sur le dépôt du manuel PHP de GitHub, ou modifier notre miroir du chapitre LuaSandbox du projet Gerrit de l'extension.
Différences avec Lua standard
LuaSandbox fournit un environnement de type bac à sable différent en quelques façons du Lua 5.1 standard.
Les fonctions et les packages suivants ne sont pas disponibles :
dofile()
,loadfile()
, et le packageio
, car ils permettent l'accès direct au système de fichiers. Si nécessaire, l'accès au système de fichiers doit être effectué à l'aide des procédures de rappel PHP.- Le package
package
, y comprisrequire()
etmodule()
, car il dépend fortement de l'accès direct au système de fichiers. Une réécriture pure Lua telle que celle utilisée dans Scribunto peut être utilisée à la place. load()
etloadstring()
, pour permettre l'analyse statique du code Lua.print()
, car il envoie ses données sur la sortie standard. Si nécessaire, les sorties doivent se faire à l'aide des procédures de rappel PHP.- La plupart du paquet
os
, parce qu'il permet la manipulation du processus et l'exécution d'autres processus.os.clock()
,os.date()
,os.difftime()
, etos.time()
restent disponibles.
- La plupart du package
debug
, parce qu'il permet la manipulation de l'état de Lua et des métadonnées de manière à corrompre le bac à sable.debug.traceback()
reste disponible.
string.dump()
, car il peut exposer des données internes.collectgarbage()
,gcinfo()
, et le packagecoroutine
n'ont pas été vérifiés en ce qui concerne la sécurité.
Les fonctionnalités suivantes ont été modifiées :
pcall()
etxpcall()
ne peuvent pas récupérer certaines erreurs, en particulier celles dûes au débordement des temporisations.tostring()
ne comprend pas les adresses de pointeurs.string.match()
a été corrigé pour limiter la profondeur de récursion et vérifie périodiquement le délai d'exécution.math.random()
etmath.randomseed()
sont remplacés par des versions qui ne partagent pas l'état avecrand()
de PHP.- Les métaméthodes
__pairs
et__ipairs
de Lua 5.2 sont prises en charge parpairs()
etipairs()
.
Historique
Au fil des années le langage des modèles wikicode de MediaWiki a gagné en fonctionnalité et est devenu plus complexe. Même déjà en 2009, les développeurs MediaWiki ont commencé à discuter l'idée d'inclure un vrai langage de script au lieu de continuer à complexifier le wikicode.
Les exigences pour un tel projet comprenaient un bac à sable robuste et des restrictions strictes sur l'utilisation de la mémoire et du temps de traitement des processeurs, car il exécuterait le code utilisateur (non fiable) sur des serveurs de production. Il doit être utilisable en se basant sur un binaire autonome, pouvant être exécuté dans un processus via une extension PHP pour une meilleure performance, ce qui est un avantage majeur.
Lorsque le développement a commencé officiellement vers 2011, quatre langages candidats ont été identifiés : Lua, JavaScript, PHP, ou un langage hypothétique WikiScript à développer. Lua a certains avantages :
- Petit (170K autonome) et rapide. L'existence de LuaJIT a aussi été considérée comme un plus.
- Conçu pour l'intégration, y compris des accroches faciles pour limiter le CPU et la mémoire.
- Utilisation facile du bac à sable, pas de variables internes globales.
- Un manuel de référence détaillé, comprenant les instructions d'intégration.
Le principal inconvénient était qu'il n'était pas aussi connu que JavaScript.
JavaScript, sous la forme du moteur V8 à l'époque, avait plusieurs inconvénients :
- Documentation minimale sur l'intégration.
- Le soutien continu de l'intégration n'est pas sûr.
- Pas d'accroche d'allocation.
- Binaire autonome très gros.
Le moteur Rhino était pire, car il était écrit en Java et ne pouvait pas être intégré au PHP en toute sécurité. PHP lui-même a été rejeté car l'intégration et le bac à sable appropriés auraient été extrêmement difficiles et la préanalyse syntaxique serait lente, et le WikiScript aurait été un projet beaucoup plus grand en ce qu'il aurait nécessité le développement d'un interpréteur (ou deux) en partant de rien.
Ainsi, Lua a été choisi, particulièrement la version 5.1 qui était disponible au moment où cette extension PHP a été développée. Les modifications apportées à la gestion de l'environnement des fonctions dans 5.2 ont empêché une simple mise à niveau depuis, voir phab:T178146 pour les détails.