2015-09-10 8 views
5

vorrei leggere una stringa da un file di input (che può o non può essere stato modificato dall'utente). Vorrei trattare questa stringa come una direttiva di formato da chiamare con un numero fisso di argomenti. Tuttavia, comprendo che alcune direttive formato (in particolare, il ~/ viene in mente) potrebbero essere utilizzati per iniettare chiamate di funzione, rendendo questo approccio intrinsecamente pericolosi.sicuro Analisi delle direttive formato in Common Lisp

Quando si utilizza read analizzare i dati in Common Lisp, la lingua fornisce la variabile dinamica *read-eval* che può essere impostato per nil per disabilitare #. iniezione di codice. Sto cercando qualcosa di simile che impedirebbe l'iniezione di codice e le chiamate di funzioni arbitrarie all'interno delle direttive di formato.

risposta

4

Se l'utente non può introdurre codice personalizzato ma solo stringhe di formato, quindi è possibile evitare i problemi di print-object. Ricordate di usare with-standard-io-syntax (o una versione personalizzata di esso) per controllare al tipo esatto di uscita si genererà (pensare *print-base*, ...).

È possibile eseguire la scansione delle stringhe di input per rilevare la presenza di ~/ (ma ~~/ è valido) e rifiutare di interpretare il formato che contiene costrutti in lista nera. Tuttavia, alcune analisi sono più difficili e potrebbe essere necessario agire in fase di esecuzione.

Ad esempio, se la stringa di formato non è corretta, è probabile che si verifichi un errore, che deve essere gestito (inoltre, è possibile fornire valori errati agli argomenti previsti).

Anche se l'utente non è dannoso, si può anche avere problemi con costrutti di iterazione:

~{<X>~:*~} 

... non si ferma perché ~:* riavvolge argomento corrente. Per gestire questo, è necessario considerare che <X> può o meno stampare qualcosa. Si potrebbe implementare entrambe le strategie:

  • hanno un timeout per limitare la formattazione tempo prende
  • hanno il flusso di portata sottostante end-of-file in scrittura troppo (ad esempio scrivere in un buffer di stringa).

Potrebbero esserci altri problemi che al momento non vedo, fare attenzione.

+1

Grazie. Non avevo nemmeno pensato a infiniti problemi di looping. Con problemi come questi, probabilmente finirò a scrivere il mio micro-linguaggio per gli specificatori di formato piuttosto che provare a modificare 'format'. –

+0

@SilvioMayolo Anche questo è un buon approccio. Ma prenditi un po 'di tempo per vedere se esistono altri formati: sto pensando a 'cl-interpol' ma potrebbero essercene altri. In bocca al lupo! – coredump

+1

Punto molto bello sui costrutti di iterazione! –

3

Non è solo il ~/ di cui dovresti preoccuparti. La bella funzionalità della stampante ha molte possibilità per l'estensione del codice, e anche ~ A può causare problemi, perché gli oggetti possono avere metodi su oggetto di stampa definito. Per esempio,

(defclass x()()) 

(defmethod print-object ((x x) stream) 
    (format *error-output* "Executing arbitrary code...~%") 
    (call-next-method x stream)) 

CL-USER> (format t "~A" (make-instance 'x)) 
Executing arbitrary code... 
#<X {1004E4B513}> 
NIL 

penso che avresti bisogno di definire per se stessi che le direttive sono sicuri, utilizzando qualsiasi criterio si considera importante, e quindi solo quelli comprendono.