WIP FPC-III support
[linux/fpc-iii.git] / Documentation / translations / it_IT / process / deprecated.rst
blob07c79d4bafcac416ce681cb1aa7d746e0372e44a
1 .. SPDX-License-Identifier: GPL-2.0
3 .. include:: ../disclaimer-ita.rst
5 :Original: :ref:`Documentation/process/deprecated.rst <deprecated>`
6 :Translator: Federico Vaga <federico.vaga@vaga.pv.it>
8 .. _it_deprecated:
10 ==============================================================================
11 Interfacce deprecate, caratteristiche del linguaggio, attributi, e convenzioni
12 ==============================================================================
14 In un mondo perfetto, sarebbe possibile prendere tutti gli usi di
15 un'interfaccia deprecata e convertirli in quella nuova, e così sarebbe
16 possibile rimuovere la vecchia interfaccia in un singolo ciclo di sviluppo.
17 Tuttavia, per via delle dimensioni del kernel, la gerarchia dei manutentori e
18 le tempistiche, non è sempre possibile fare questo tipo di conversione tutta
19 in una volta. Questo significa che nuove istanze di una vecchia interfaccia
20 potrebbero aggiungersi al kernel proprio quando si sta cercando di rimuoverle,
21 aumentando così il carico di lavoro. Al fine di istruire gli sviluppatori su
22 cosa è considerato deprecato (e perché), è stata create la seguente lista a cui
23 fare riferimento quando qualcuno propone modifiche che usano cose deprecate.
25 __deprecated
26 ------------
27 Nonostante questo attributo marchi visibilmente un interfaccia come deprecata,
28 `non produce più alcun avviso durante la compilazione
29 <https://git.kernel.org/linus/771c035372a036f83353eef46dbb829780330234>`_
30 perché uno degli obiettivi del kernel è quello di compilare senza avvisi;
31 inoltre, nessuno stava agendo per rimuovere queste interfacce. Nonostante l'uso
32 di `__deprecated` in un file d'intestazione sia opportuno per segnare una
33 interfaccia come 'vecchia', questa non è una soluzione completa. L'interfaccia
34 deve essere rimossa dal kernel, o aggiunta a questo documento per scoraggiarne
35 l'uso.
37 BUG() e BUG_ON()
38 ----------------
39 Al loro posto usate WARN() e WARN_ON() per gestire le
40 condizioni "impossibili" e gestitele come se fosse possibile farlo.
41 Nonostante le funzioni della famiglia BUG() siano state progettate
42 per asserire "situazioni impossibili" e interrompere in sicurezza un
43 thread del kernel, queste si sono rivelate essere troppo rischiose
44 (per esempio, in quale ordine rilasciare i *lock*? Ci sono stati che
45 sono stati ripristinati?). Molto spesso l'uso di BUG()
46 destabilizza il sistema o lo corrompe del tutto, il che rende
47 impossibile un'attività di debug o anche solo leggere un rapporto
48 circa l'errore.  Linus ha un'opinione molto critica al riguardo:
49 `email 1
50 <https://lore.kernel.org/lkml/CA+55aFy6jNLsywVYdGp83AMrXBo_P-pkjkphPGrO=82SPKCpLQ@mail.gmail.com/>`_,
51 `email 2
52 <https://lore.kernel.org/lkml/CAHk-=whDHsbK3HTOpTF=ue_o04onRwTEaK_ZoJp_fjbqq4+=Jw@mail.gmail.com/>`_
54 Tenete presente che la famiglia di funzioni WARN() dovrebbe essere
55 usato solo per situazioni che si suppone siano "impossibili".  Se
56 volete avvisare gli utenti riguardo a qualcosa di possibile anche se
57 indesiderato, usare le funzioni della famiglia pr_warn().  Chi
58 amministra il sistema potrebbe aver attivato l'opzione sysctl
59 *panic_on_warn* per essere sicuri che il sistema smetta di funzionare
60 in caso si verifichino delle condizioni "inaspettate". (per esempio,
61 date un'occhiata al questo `commit
62 <https://git.kernel.org/linus/d4689846881d160a4d12a514e991a740bcb5d65a>`_)
64 Calcoli codificati negli argomenti di un allocatore
65 ----------------------------------------------------
66 Il calcolo dinamico delle dimensioni (specialmente le moltiplicazioni) non
67 dovrebbero essere fatto negli argomenti di funzioni di allocazione di memoria
68 (o simili) per via del rischio di overflow. Questo può portare a valori più
69 piccoli di quelli che il chiamante si aspettava. L'uso di questo modo di
70 allocare può portare ad un overflow della memoria di heap e altri
71 malfunzionamenti. (Si fa eccezione per valori numerici per i quali il
72 compilatore può generare avvisi circa un potenziale overflow. Tuttavia usare
73 i valori numerici come suggerito di seguito è innocuo).
75 Per esempio, non usate ``count * size`` come argomento::
77         foo = kmalloc(count * size, GFP_KERNEL);
79 Al suo posto, si dovrebbe usare l'allocatore a due argomenti::
81         foo = kmalloc_array(count, size, GFP_KERNEL);
83 Se questo tipo di allocatore non è disponibile, allora dovrebbero essere usate
84 le funzioni del tipo *saturate-on-overflow*::
86         bar = vmalloc(array_size(count, size));
88 Un altro tipico caso da evitare è quello di calcolare la dimensione di una
89 struttura seguita da un vettore di altre strutture, come nel seguente caso::
91         header = kzalloc(sizeof(*header) + count * sizeof(*header->item),
92                          GFP_KERNEL);
94 Invece, usate la seguente funzione::
96         header = kzalloc(struct_size(header, item, count), GFP_KERNEL);
98 .. note:: Se per caso state usando struct_size() su una struttura dati che
99           in coda contiene un array di lunghezza zero o uno, allora siete
100           invitati a riorganizzare il vostro codice usando il
101           `flexible array member <#zero-length-and-one-element-arrays>`_.
103 Per maggiori dettagli fate riferimento a array_size(),
104 array3_size(), e struct_size(), così come la famiglia di
105 funzioni check_add_overflow() e check_mul_overflow().
107 simple_strtol(), simple_strtoll(), simple_strtoul(), simple_strtoull()
108 ----------------------------------------------------------------------
109 Le funzioni simple_strtol(), simple_strtoll(),
110 simple_strtoul(), e simple_strtoull() ignorano volutamente
111 i possibili overflow, e questo può portare il chiamante a generare risultati
112 inaspettati. Le rispettive funzioni kstrtol(), kstrtoll(),
113 kstrtoul(), e kstrtoull() sono da considerarsi le corrette
114 sostitute; tuttavia va notato che queste richiedono che la stringa sia
115 terminata con il carattere NUL o quello di nuova riga.
117 strcpy()
118 --------
119 La funzione strcpy() non fa controlli agli estremi del buffer
120 di destinazione. Questo può portare ad un overflow oltre i limiti del
121 buffer e generare svariati tipi di malfunzionamenti. Nonostante l'opzione
122 `CONFIG_FORTIFY_SOURCE=y` e svariate opzioni del compilatore aiutano
123 a ridurne il rischio, non c'è alcuna buona ragione per continuare ad usare
124 questa funzione. La versione sicura da usare è strscpy(), tuttavia va
125 prestata attenzione a tutti quei casi dove viene usato il valore di
126 ritorno di strcpy().  La funzione strscpy() non ritorna un puntatore
127 alla destinazione, ma un contatore dei byte non NUL copiati (oppure
128 un errno negativo se la stringa è stata troncata).
130 strncpy() su stringe terminate con NUL
131 --------------------------------------
132 L'utilizzo di strncpy() non fornisce alcuna garanzia sul fatto che
133 il buffer di destinazione verrà terminato con il carattere NUL. Questo
134 potrebbe portare a diversi overflow di lettura o altri malfunzionamenti
135 causati, appunto, dalla mancanza del terminatore. Questa estende la
136 terminazione nel buffer di destinazione quando la stringa d'origine è più
137 corta; questo potrebbe portare ad una penalizzazione delle prestazioni per
138 chi usa solo stringe terminate. La versione sicura da usare è
139 strscpy(), tuttavia va prestata attenzione a tutti quei casi dove
140 viene usato il valore di ritorno di strncpy().  La funzione strscpy()
141 non ritorna un puntatore alla destinazione, ma un contatore dei byte
142 non NUL copiati (oppure un errno negativo se la stringa è stata
143 troncata). Tutti i casi che necessitano di estendere la
144 terminazione con NUL dovrebbero usare strscpy_pad().
146 Se il chiamate no usa stringhe terminate con NUL, allore strncpy()
147 può continuare ad essere usata, ma i buffer di destinazione devono essere
148 marchiati con l'attributo `__nonstring <https://gcc.gnu.org/onlinedocs/gcc/Common-Variable-Attributes.html>`_
149 per evitare avvisi durante la compilazione.
151 strlcpy()
152 ---------
153 La funzione strlcpy(), per prima cosa, legge interamente il buffer di
154 origine, magari leggendo più di quanto verrà effettivamente copiato. Questo
155 è inefficiente e può portare a overflow di lettura quando la stringa non è
156 terminata con NUL. La versione sicura da usare è strscpy(), tuttavia
157 va prestata attenzione a tutti quei casi dove viene usato il valore di
158 ritorno di strlcpy(), dato che strscpy() ritorna un valore di errno
159 negativo quanto la stringa viene troncata.
161 Segnaposto %p nella stringa di formato
162 --------------------------------------
164 Tradizionalmente, l'uso del segnaposto "%p" nella stringa di formato
165 esponne un indirizzo di memoria in dmesg, proc, sysfs, eccetera.  Per
166 evitare che questi indirizzi vengano sfruttati da malintenzionati,
167 tutto gli usi di "%p" nel kernel rappresentano l'hash dell'indirizzo,
168 rendendolo di fatto inutilizzabile.  Nuovi usi di "%p" non dovrebbero
169 essere aggiunti al kernel.  Per una rappresentazione testuale di un
170 indirizzo usate "%pS", l'output è migliore perché mostrerà il nome del
171 simbolo.  Per tutto il resto, semplicemente non usate "%p".
173 Parafrasando la `guida
174 <https://lore.kernel.org/lkml/CA+55aFwQEd_d40g4mUCSsVRZzrFPUJt74vc6PPpb675hYNXcKw@mail.gmail.com/>`_
175 di Linus:
177 - Se il valore hash di "%p" è inutile, chiediti se il puntatore stesso
178   è importante. Forse dovrebbe essere rimosso del tutto?
179 - Se credi davvero che il vero valore del puntatore sia importante,
180   perché alcuni stati del sistema o i livelli di privilegi di un
181   utente sono considerati "special"? Se pensi di poterlo giustificare
182   (in un commento e nel messaggio del commit) abbastanza bene da
183   affrontare il giudizio di Linus, allora forse potrai usare "%px",
184   assicurandosi anche di averne il permesso.
186 Infine, sappi che un cambio in favore di "%p" con hash `non verrà
187 accettato
188 <https://lore.kernel.org/lkml/CA+55aFwieC1-nAs+NFq9RTwaR8ef9hWa4MjNBWL41F-8wM49eA@mail.gmail.com/>`_.
190 Vettori a dimensione variabile (VLA)
191 ------------------------------------
193 Usare VLA sullo stack produce codice molto peggiore rispetto a quando si usano
194 vettori a dimensione fissa. Questi `problemi di prestazioni <https://git.kernel.org/linus/02361bc77888>`_,
195 tutt'altro che banali, sono già un motivo valido per eliminare i VLA; in
196 aggiunta sono anche un problema per la sicurezza. La crescita dinamica di un
197 vettore nello stack potrebbe eccedere la memoria rimanente in tale segmento.
198 Questo può portare a dei malfunzionamenti, potrebbe sovrascrivere
199 dati importanti alla fine dello stack (quando il kernel è compilato senza
200 `CONFIG_THREAD_INFO_IN_TASK=y`), o sovrascrivere un pezzo di memoria adiacente
201 allo stack (quando il kernel è compilato senza `CONFIG_VMAP_STACK=y`).
203 Salto implicito nell'istruzione switch-case
204 -------------------------------------------
206 Il linguaggio C permette ai casi di un'istruzione `switch` di saltare al
207 prossimo caso quando l'istruzione "break" viene omessa alla fine del caso
208 corrente. Tuttavia questo rende il codice ambiguo perché non è sempre ovvio se
209 l'istruzione "break" viene omessa intenzionalmente o è un baco. Per esempio,
210 osservando il seguente pezzo di codice non è chiaro se lo stato
211 `STATE_ONE` è stato progettato apposta per eseguire anche `STATE_TWO`::
213   switch (value) {
214   case STATE_ONE:
215           do_something();
216   case STATE_TWO:
217           do_other();
218           break;
219   default:
220           WARN("unknown state");
221   }
223 Dato che c'è stata una lunga lista di problemi `dovuti alla mancanza dell'istruzione
224 "break" <https://cwe.mitre.org/data/definitions/484.html>`_, oggigiorno non
225 permettiamo più che vi sia un "salto implicito" (*fall-through*). Per
226 identificare un salto implicito intenzionale abbiamo adottato la pseudo
227 parola chiave 'fallthrough' che viene espansa nell'estensione di gcc
228 `__attribute__((fallthrough))` `Statement Attributes
229 <https://gcc.gnu.org/onlinedocs/gcc/Statement-Attributes.html>`_.
230 (Quando la sintassi C17/C18 `[[fallthrough]]` sarà più comunemente
231 supportata dai compilatori C, analizzatori statici, e dagli IDE,
232 allora potremo usare quella sintassi per la pseudo parola chiave)
234 Quando la sintassi [[fallthrough]] sarà più comunemente supportata dai
235 compilatori, analizzatori statici, e ambienti di sviluppo IDE,
236 allora potremo usarla anche noi.
238 Ne consegue che tutti i blocchi switch/case devono finire in uno dei seguenti
239 modi:
241 * ``break;``
242 * `fallthrough;``
243 * ``continue;``
244 * ``goto <label>;``
245 * ``return [expression];``
247 Array di lunghezza zero o con un solo elemento
248 ----------------------------------------------
249 All'interno del kernel ricorre spesso la necessita di avere membri
250 di dimensione variabile all'interno di una struttura dati. In questi
251 casi il codice del kernel dovrebbe usare sempre i `"flexible array
252 member" <https://en.wikipedia.org/wiki/Flexible_array_member>`_. La
253 tecnica degli array a lunghezza nulla o di un solo elemento non
254 dovrebbe essere più usata.
256 Nel codice C più vecchio, la dichiarazione di un membro di dimensione
257 variabile in coda ad una struttura dati veniva fatto dichiarando un
258 array di un solo elemento posizionato alla fine della struttura dati::
260         struct something {
261                 size_t count;
262                 struct foo items[1];
263         };
265 Questo ha portato ad un calcolo di sizeof() traballante (dovrebbe
266 rimuovere la dimensione del singolo elemento in coda per calcolare la
267 dimensione esatta dell' "intestazione"). Per evitare questi problemi è
268 stata introdotta un' `estensione a GNU C
269 <https://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html>`_ che
270 permettesse la dichiarazione di array a lungezza zero::
272         struct something {
273                 size_t count;
274                 struct foo items[0];
275         };
277 Ma questo ha portato nuovi problemi, e non ha risolto alcuni dei
278 problemi che affliggono entrambe le tecniche: per esempio
279 l'impossibilità di riconoscere se un array di quel tipo viene usato
280 nel mezzo di una struttura dati e _non_ alla fine (potrebbe accadere
281 sia direttamente, sia indirettamente quando si usano le unioni o le
282 strutture di strutture).
284 Lo standard C99 introduce i "flexible array members". Questi array non
285 hanno una dimensione nella loro dichiarazione::
287         struct something {
288                 size_t count;
289                 struct foo items[];
290         };
292 Questo è il modo con cui ci si aspetta che vengano dichiarati gli
293 elementi di lunghezza variabile in coda alle strutture dati.  Permette
294 al compilatore di produrre errori quando gli array flessibili non si
295 trovano alla fine della struttura dati, il che permette di prevenire
296 alcuni tipi di bachi dovuti a `comportamenti inaspettati
297 <https://git.kernel.org/linus/76497732932f15e7323dc805e8ea8dc11bb587cf>`_.
298 Inoltre, permette al compilatore di analizzare correttamente le
299 dimensioni degli array (attraverso sizeof(), `CONFIG_FORTIFY_SOURCE`,
300 e `CONFIG_UBSAN_BOUNDS`). Per esempio, non esiste alcun meccanismo in
301 grado di avvisarci che il seguente uso di sizeof() dia sempre come
302 zero come risultato::
304         struct something {
305                 size_t count;
306                 struct foo items[0];
307         };
309         struct something *instance;
311         instance = kmalloc(struct_size(instance, items, count), GFP_KERNEL);
312         instance->count = count;
314         size = sizeof(instance->items) * instance->count;
315         memcpy(instance->items, source, size);
317 Il valore di ``size`` nell'ultima riga sarà ``zero``, quando uno
318 invece si aspetterebbe che il suo valore sia la dimensione totale in
319 byte dell'allocazione dynamica che abbiamo appena fatto per l'array
320 ``items``. Qui un paio di esempi reali del problema: `collegamento 1
321 <https://git.kernel.org/linus/f2cd32a443da694ac4e28fbf4ac6f9d5cc63a539>`_,
322 `collegamento 2
323 <https://git.kernel.org/linus/ab91c2a89f86be2898cee208d492816ec238b2cf>`_.
324 Invece, `i flexible array members hanno un tipo incompleto, e quindi
325 sizeof() non può essere applicato
326 <https://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html>`_; dunque ogni
327 uso scorretto di questo operatore verrà identificato immediatamente
328 durante la compilazione.
330 Per quanto riguarda gli array di un solo elemento, bisogna essere
331 consapevoli che `questi array occupano almeno quanto lo spazio di un
332 singolo oggetti dello stesso tipo
333 <https://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html>`_, e quindi
334 contribuiscono al calcolo della dimensione della struttura che li
335 contiene. In questo caso è facile commettere errori quando si vuole
336 calcolare la dimensione totale della memoria totale da allocare per
337 una struttura dati::
339         struct something {
340                 size_t count;
341                 struct foo items[1];
342         };
344         struct something *instance;
346         instance = kmalloc(struct_size(instance, items, count - 1), GFP_KERNEL);
347         instance->count = count;
349         size = sizeof(instance->items) * instance->count;
350         memcpy(instance->items, source, size);
352 In questo esempio ci siamo dovuti ricordare di usare ``count - 1`` in
353 struct_size(), altrimenti avremmo --inavvertitamente-- allocato
354 memoria per un oggetti ``items`` in più. Il modo più pulito e meno
355 propenso agli errori è quello di usare i `flexible array member`, in
356 combinazione con struct_size() e flex_array_size()::
358         struct something {
359                 size_t count;
360                 struct foo items[];
361         };
363         struct something *instance;
365         instance = kmalloc(struct_size(instance, items, count), GFP_KERNEL);
366         instance->count = count;
368         memcpy(instance->items, source, flex_array_size(instance, items, instance->count));