198348577SFederico Vaga.. SPDX-License-Identifier: GPL-2.0 298348577SFederico Vaga 398348577SFederico Vaga.. include:: ../disclaimer-ita.rst 498348577SFederico Vaga 598348577SFederico Vaga:Original: :ref:`Documentation/process/deprecated.rst <deprecated>` 698348577SFederico Vaga:Translator: Federico Vaga <federico.vaga@vaga.pv.it> 798348577SFederico Vaga 898348577SFederico Vaga.. _it_deprecated: 998348577SFederico Vaga 1098348577SFederico Vaga============================================================================== 1198348577SFederico VagaInterfacce deprecate, caratteristiche del linguaggio, attributi, e convenzioni 1298348577SFederico Vaga============================================================================== 1398348577SFederico Vaga 1498348577SFederico VagaIn un mondo perfetto, sarebbe possibile prendere tutti gli usi di 1598348577SFederico Vagaun'interfaccia deprecata e convertirli in quella nuova, e così sarebbe 1698348577SFederico Vagapossibile rimuovere la vecchia interfaccia in un singolo ciclo di sviluppo. 1798348577SFederico VagaTuttavia, per via delle dimensioni del kernel, la gerarchia dei manutentori e 1898348577SFederico Vagale tempistiche, non è sempre possibile fare questo tipo di conversione tutta 1998348577SFederico Vagain una volta. Questo significa che nuove istanze di una vecchia interfaccia 2098348577SFederico Vagapotrebbero aggiungersi al kernel proprio quando si sta cercando di rimuoverle, 2198348577SFederico Vagaaumentando così il carico di lavoro. Al fine di istruire gli sviluppatori su 2298348577SFederico Vagacosa è considerato deprecato (e perché), è stata create la seguente lista a cui 2398348577SFederico Vagafare riferimento quando qualcuno propone modifiche che usano cose deprecate. 2498348577SFederico Vaga 2598348577SFederico Vaga__deprecated 2698348577SFederico Vaga------------ 2798348577SFederico VagaNonostante questo attributo marchi visibilmente un interfaccia come deprecata, 2898348577SFederico Vaga`non produce più alcun avviso durante la compilazione 2998348577SFederico Vaga<https://git.kernel.org/linus/771c035372a036f83353eef46dbb829780330234>`_ 3098348577SFederico Vagaperché uno degli obiettivi del kernel è quello di compilare senza avvisi; 3198348577SFederico Vagainoltre, nessuno stava agendo per rimuovere queste interfacce. Nonostante l'uso 3298348577SFederico Vagadi `__deprecated` in un file d'intestazione sia opportuno per segnare una 3398348577SFederico Vagainterfaccia come 'vecchia', questa non è una soluzione completa. L'interfaccia 3498348577SFederico Vagadeve essere rimossa dal kernel, o aggiunta a questo documento per scoraggiarne 3598348577SFederico Vagal'uso. 3698348577SFederico Vaga 37b67aa4efSFederico VagaBUG() e BUG_ON() 38b67aa4efSFederico Vaga---------------- 39b67aa4efSFederico VagaAl loro posto usate WARN() e WARN_ON() per gestire le 40b67aa4efSFederico Vagacondizioni "impossibili" e gestitele come se fosse possibile farlo. 41b67aa4efSFederico VagaNonostante le funzioni della famiglia BUG() siano state progettate 42b67aa4efSFederico Vagaper asserire "situazioni impossibili" e interrompere in sicurezza un 43b67aa4efSFederico Vagathread del kernel, queste si sono rivelate essere troppo rischiose 44b67aa4efSFederico Vaga(per esempio, in quale ordine rilasciare i *lock*? Ci sono stati che 45b67aa4efSFederico Vagasono stati ripristinati?). Molto spesso l'uso di BUG() 46b67aa4efSFederico Vagadestabilizza il sistema o lo corrompe del tutto, il che rende 47b67aa4efSFederico Vagaimpossibile un'attività di debug o anche solo leggere un rapporto 48b67aa4efSFederico Vagacirca l'errore. Linus ha un'opinione molto critica al riguardo: 49b67aa4efSFederico Vaga`email 1 50b67aa4efSFederico Vaga<https://lore.kernel.org/lkml/CA+55aFy6jNLsywVYdGp83AMrXBo_P-pkjkphPGrO=82SPKCpLQ@mail.gmail.com/>`_, 51b67aa4efSFederico Vaga`email 2 52b67aa4efSFederico Vaga<https://lore.kernel.org/lkml/CAHk-=whDHsbK3HTOpTF=ue_o04onRwTEaK_ZoJp_fjbqq4+=Jw@mail.gmail.com/>`_ 53b67aa4efSFederico Vaga 54b67aa4efSFederico VagaTenete presente che la famiglia di funzioni WARN() dovrebbe essere 55b67aa4efSFederico Vagausato solo per situazioni che si suppone siano "impossibili". Se 56b67aa4efSFederico Vagavolete avvisare gli utenti riguardo a qualcosa di possibile anche se 57b67aa4efSFederico Vagaindesiderato, usare le funzioni della famiglia pr_warn(). Chi 58b67aa4efSFederico Vagaamministra il sistema potrebbe aver attivato l'opzione sysctl 59b67aa4efSFederico Vaga*panic_on_warn* per essere sicuri che il sistema smetta di funzionare 60b67aa4efSFederico Vagain caso si verifichino delle condizioni "inaspettate". (per esempio, 61b67aa4efSFederico Vagadate un'occhiata al questo `commit 62b67aa4efSFederico Vaga<https://git.kernel.org/linus/d4689846881d160a4d12a514e991a740bcb5d65a>`_) 63b67aa4efSFederico Vaga 6498348577SFederico VagaCalcoli codificati negli argomenti di un allocatore 6598348577SFederico Vaga---------------------------------------------------- 6698348577SFederico VagaIl calcolo dinamico delle dimensioni (specialmente le moltiplicazioni) non 6798348577SFederico Vagadovrebbero essere fatto negli argomenti di funzioni di allocazione di memoria 6898348577SFederico Vaga(o simili) per via del rischio di overflow. Questo può portare a valori più 6998348577SFederico Vagapiccoli di quelli che il chiamante si aspettava. L'uso di questo modo di 7098348577SFederico Vagaallocare può portare ad un overflow della memoria di heap e altri 7198348577SFederico Vagamalfunzionamenti. (Si fa eccezione per valori numerici per i quali il 72da1d9cafSFederico Vagacompilatore può generare avvisi circa un potenziale overflow. Tuttavia, anche in 73da1d9cafSFederico Vagaquesti casi è preferibile riscrivere il codice come suggerito di seguito). 7498348577SFederico Vaga 7598348577SFederico VagaPer esempio, non usate ``count * size`` come argomento:: 7698348577SFederico Vaga 7798348577SFederico Vaga foo = kmalloc(count * size, GFP_KERNEL); 7898348577SFederico Vaga 7998348577SFederico VagaAl suo posto, si dovrebbe usare l'allocatore a due argomenti:: 8098348577SFederico Vaga 8198348577SFederico Vaga foo = kmalloc_array(count, size, GFP_KERNEL); 8298348577SFederico Vaga 83da1d9cafSFederico VagaNello specifico, kmalloc() può essere sostituta da kmalloc_array(), e kzalloc() 84da1d9cafSFederico Vagada kcalloc(). 85da1d9cafSFederico Vaga 8698348577SFederico VagaSe questo tipo di allocatore non è disponibile, allora dovrebbero essere usate 8798348577SFederico Vagale funzioni del tipo *saturate-on-overflow*:: 8898348577SFederico Vaga 8998348577SFederico Vaga bar = vmalloc(array_size(count, size)); 9098348577SFederico Vaga 9198348577SFederico VagaUn altro tipico caso da evitare è quello di calcolare la dimensione di una 9298348577SFederico Vagastruttura seguita da un vettore di altre strutture, come nel seguente caso:: 9398348577SFederico Vaga 9498348577SFederico Vaga header = kzalloc(sizeof(*header) + count * sizeof(*header->item), 9598348577SFederico Vaga GFP_KERNEL); 9698348577SFederico Vaga 9798348577SFederico VagaInvece, usate la seguente funzione:: 9898348577SFederico Vaga 9998348577SFederico Vaga header = kzalloc(struct_size(header, item, count), GFP_KERNEL); 10098348577SFederico Vaga 101ac771142SFederico Vaga.. note:: Se per caso state usando struct_size() su una struttura dati che 102ac771142SFederico Vaga in coda contiene un array di lunghezza zero o uno, allora siete 103ac771142SFederico Vaga invitati a riorganizzare il vostro codice usando il 104ac771142SFederico Vaga `flexible array member <#zero-length-and-one-element-arrays>`_. 105ac771142SFederico Vaga 106da1d9cafSFederico VagaPer altri calcoli, usate le funzioni size_mul(), size_add(), e size_sub(). Per 107da1d9cafSFederico Vagaesempio, al posto di:: 108da1d9cafSFederico Vaga 109da1d9cafSFederico Vaga foo = krealloc(current_size + chunk_size * (count - 3), GFP_KERNEL); 110da1d9cafSFederico Vaga 111da1d9cafSFederico Vagadovreste scrivere: 112da1d9cafSFederico Vaga 113da1d9cafSFederico Vaga foo = krealloc(size_add(current_size, 114da1d9cafSFederico Vaga size_mul(chunk_size, 115da1d9cafSFederico Vaga size_sub(count, 3))), GFP_KERNEL); 116da1d9cafSFederico Vaga 117da1d9cafSFederico VagaPer maggiori dettagli fate riferimento a array3_size() e flex_array_size(), ma 118da1d9cafSFederico Vagaanche le funzioni della famiglia check_mul_overflow(), check_add_overflow(), 119da1d9cafSFederico Vagacheck_sub_overflow(), e check_shl_overflow(). 12098348577SFederico Vaga 12198348577SFederico Vagasimple_strtol(), simple_strtoll(), simple_strtoul(), simple_strtoull() 12298348577SFederico Vaga---------------------------------------------------------------------- 123b67aa4efSFederico VagaLe funzioni simple_strtol(), simple_strtoll(), 124b67aa4efSFederico Vagasimple_strtoul(), e simple_strtoull() ignorano volutamente 12598348577SFederico Vagai possibili overflow, e questo può portare il chiamante a generare risultati 126b67aa4efSFederico Vagainaspettati. Le rispettive funzioni kstrtol(), kstrtoll(), 127b67aa4efSFederico Vagakstrtoul(), e kstrtoull() sono da considerarsi le corrette 12898348577SFederico Vagasostitute; tuttavia va notato che queste richiedono che la stringa sia 12998348577SFederico Vagaterminata con il carattere NUL o quello di nuova riga. 13098348577SFederico Vaga 13198348577SFederico Vagastrcpy() 13298348577SFederico Vaga-------- 133b67aa4efSFederico VagaLa funzione strcpy() non fa controlli agli estremi del buffer 13498348577SFederico Vagadi destinazione. Questo può portare ad un overflow oltre i limiti del 13598348577SFederico Vagabuffer e generare svariati tipi di malfunzionamenti. Nonostante l'opzione 13698348577SFederico Vaga`CONFIG_FORTIFY_SOURCE=y` e svariate opzioni del compilatore aiutano 13798348577SFederico Vagaa ridurne il rischio, non c'è alcuna buona ragione per continuare ad usare 138ac771142SFederico Vagaquesta funzione. La versione sicura da usare è strscpy(), tuttavia va 139ac771142SFederico Vagaprestata attenzione a tutti quei casi dove viene usato il valore di 140ac771142SFederico Vagaritorno di strcpy(). La funzione strscpy() non ritorna un puntatore 141ac771142SFederico Vagaalla destinazione, ma un contatore dei byte non NUL copiati (oppure 142ac771142SFederico Vagaun errno negativo se la stringa è stata troncata). 14398348577SFederico Vaga 14498348577SFederico Vagastrncpy() su stringe terminate con NUL 14598348577SFederico Vaga-------------------------------------- 146b67aa4efSFederico VagaL'utilizzo di strncpy() non fornisce alcuna garanzia sul fatto che 14798348577SFederico Vagail buffer di destinazione verrà terminato con il carattere NUL. Questo 14898348577SFederico Vagapotrebbe portare a diversi overflow di lettura o altri malfunzionamenti 14998348577SFederico Vagacausati, appunto, dalla mancanza del terminatore. Questa estende la 15098348577SFederico Vagaterminazione nel buffer di destinazione quando la stringa d'origine è più 15198348577SFederico Vagacorta; questo potrebbe portare ad una penalizzazione delle prestazioni per 15298348577SFederico Vagachi usa solo stringe terminate. La versione sicura da usare è 153ac771142SFederico Vagastrscpy(), tuttavia va prestata attenzione a tutti quei casi dove 154ac771142SFederico Vagaviene usato il valore di ritorno di strncpy(). La funzione strscpy() 155ac771142SFederico Vaganon ritorna un puntatore alla destinazione, ma un contatore dei byte 156ac771142SFederico Vaganon NUL copiati (oppure un errno negativo se la stringa è stata 157ac771142SFederico Vagatroncata). Tutti i casi che necessitano di estendere la 158ac771142SFederico Vagaterminazione con NUL dovrebbero usare strscpy_pad(). 15998348577SFederico Vaga 160053f8fc7SKees CookSe il chiamate no usa stringhe terminate con NUL, allore strncpy() 16198348577SFederico Vagapuò continuare ad essere usata, ma i buffer di destinazione devono essere 16298348577SFederico Vagamarchiati con l'attributo `__nonstring <https://gcc.gnu.org/onlinedocs/gcc/Common-Variable-Attributes.html>`_ 16398348577SFederico Vagaper evitare avvisi durante la compilazione. 16498348577SFederico Vaga 16598348577SFederico Vagastrlcpy() 16698348577SFederico Vaga--------- 167b67aa4efSFederico VagaLa funzione strlcpy(), per prima cosa, legge interamente il buffer di 16898348577SFederico Vagaorigine, magari leggendo più di quanto verrà effettivamente copiato. Questo 16998348577SFederico Vagaè inefficiente e può portare a overflow di lettura quando la stringa non è 170ac771142SFederico Vagaterminata con NUL. La versione sicura da usare è strscpy(), tuttavia 171ac771142SFederico Vagava prestata attenzione a tutti quei casi dove viene usato il valore di 172ac771142SFederico Vagaritorno di strlcpy(), dato che strscpy() ritorna un valore di errno 173ac771142SFederico Vaganegativo quanto la stringa viene troncata. 174b67aa4efSFederico Vaga 175b67aa4efSFederico VagaSegnaposto %p nella stringa di formato 176b67aa4efSFederico Vaga-------------------------------------- 177b67aa4efSFederico Vaga 178b67aa4efSFederico VagaTradizionalmente, l'uso del segnaposto "%p" nella stringa di formato 179b67aa4efSFederico Vagaesponne un indirizzo di memoria in dmesg, proc, sysfs, eccetera. Per 180b67aa4efSFederico Vagaevitare che questi indirizzi vengano sfruttati da malintenzionati, 181b67aa4efSFederico Vagatutto gli usi di "%p" nel kernel rappresentano l'hash dell'indirizzo, 182b67aa4efSFederico Vagarendendolo di fatto inutilizzabile. Nuovi usi di "%p" non dovrebbero 183b67aa4efSFederico Vagaessere aggiunti al kernel. Per una rappresentazione testuale di un 184b67aa4efSFederico Vagaindirizzo usate "%pS", l'output è migliore perché mostrerà il nome del 185b67aa4efSFederico Vagasimbolo. Per tutto il resto, semplicemente non usate "%p". 186b67aa4efSFederico Vaga 187b67aa4efSFederico VagaParafrasando la `guida 188b67aa4efSFederico Vaga<https://lore.kernel.org/lkml/CA+55aFwQEd_d40g4mUCSsVRZzrFPUJt74vc6PPpb675hYNXcKw@mail.gmail.com/>`_ 189b67aa4efSFederico Vagadi Linus: 190b67aa4efSFederico Vaga 191b67aa4efSFederico Vaga- Se il valore hash di "%p" è inutile, chiediti se il puntatore stesso 192b67aa4efSFederico Vaga è importante. Forse dovrebbe essere rimosso del tutto? 193b67aa4efSFederico Vaga- Se credi davvero che il vero valore del puntatore sia importante, 194b67aa4efSFederico Vaga perché alcuni stati del sistema o i livelli di privilegi di un 195b67aa4efSFederico Vaga utente sono considerati "special"? Se pensi di poterlo giustificare 196b67aa4efSFederico Vaga (in un commento e nel messaggio del commit) abbastanza bene da 197b67aa4efSFederico Vaga affrontare il giudizio di Linus, allora forse potrai usare "%px", 198b67aa4efSFederico Vaga assicurandosi anche di averne il permesso. 199b67aa4efSFederico Vaga 200191cf329SFederico VagaPotete disabilitare temporaneamente l'hashing di "%p" nel caso in cui questa 201191cf329SFederico Vagafunzionalità vi sia d'ostacolo durante una sessione di debug. Per farlo 202191cf329SFederico Vagaaggiungete l'opzione di debug "`no_hash_pointers 203191cf329SFederico Vaga<https://git.kernel.org/linus/5ead723a20e0447bc7db33dc3070b420e5f80aa6>`_" alla 204191cf329SFederico Vagariga di comando del kernel. 20598348577SFederico Vaga 20698348577SFederico VagaVettori a dimensione variabile (VLA) 20798348577SFederico Vaga------------------------------------ 20898348577SFederico Vaga 20998348577SFederico VagaUsare VLA sullo stack produce codice molto peggiore rispetto a quando si usano 21098348577SFederico Vagavettori a dimensione fissa. Questi `problemi di prestazioni <https://git.kernel.org/linus/02361bc77888>`_, 21198348577SFederico Vagatutt'altro che banali, sono già un motivo valido per eliminare i VLA; in 21298348577SFederico Vagaaggiunta sono anche un problema per la sicurezza. La crescita dinamica di un 21398348577SFederico Vagavettore nello stack potrebbe eccedere la memoria rimanente in tale segmento. 21498348577SFederico VagaQuesto può portare a dei malfunzionamenti, potrebbe sovrascrivere 21598348577SFederico Vagadati importanti alla fine dello stack (quando il kernel è compilato senza 21698348577SFederico Vaga`CONFIG_THREAD_INFO_IN_TASK=y`), o sovrascrivere un pezzo di memoria adiacente 21798348577SFederico Vagaallo stack (quando il kernel è compilato senza `CONFIG_VMAP_STACK=y`). 218b67aa4efSFederico Vaga 219b67aa4efSFederico VagaSalto implicito nell'istruzione switch-case 220b67aa4efSFederico Vaga------------------------------------------- 221b67aa4efSFederico Vaga 222b67aa4efSFederico VagaIl linguaggio C permette ai casi di un'istruzione `switch` di saltare al 223b67aa4efSFederico Vagaprossimo caso quando l'istruzione "break" viene omessa alla fine del caso 224b67aa4efSFederico Vagacorrente. Tuttavia questo rende il codice ambiguo perché non è sempre ovvio se 225b67aa4efSFederico Vagal'istruzione "break" viene omessa intenzionalmente o è un baco. Per esempio, 226b67aa4efSFederico Vagaosservando il seguente pezzo di codice non è chiaro se lo stato 227b67aa4efSFederico Vaga`STATE_ONE` è stato progettato apposta per eseguire anche `STATE_TWO`:: 228b67aa4efSFederico Vaga 229b67aa4efSFederico Vaga switch (value) { 230b67aa4efSFederico Vaga case STATE_ONE: 231b67aa4efSFederico Vaga do_something(); 232b67aa4efSFederico Vaga case STATE_TWO: 233b67aa4efSFederico Vaga do_other(); 234b67aa4efSFederico Vaga break; 235b67aa4efSFederico Vaga default: 236b67aa4efSFederico Vaga WARN("unknown state"); 237b67aa4efSFederico Vaga } 238b67aa4efSFederico Vaga 239b67aa4efSFederico VagaDato che c'è stata una lunga lista di problemi `dovuti alla mancanza dell'istruzione 240b67aa4efSFederico Vaga"break" <https://cwe.mitre.org/data/definitions/484.html>`_, oggigiorno non 241b67aa4efSFederico Vagapermettiamo più che vi sia un "salto implicito" (*fall-through*). Per 242b67aa4efSFederico Vagaidentificare un salto implicito intenzionale abbiamo adottato la pseudo 243b67aa4efSFederico Vagaparola chiave 'fallthrough' che viene espansa nell'estensione di gcc 244b67aa4efSFederico Vaga`__attribute__((fallthrough))` `Statement Attributes 245b67aa4efSFederico Vaga<https://gcc.gnu.org/onlinedocs/gcc/Statement-Attributes.html>`_. 246b67aa4efSFederico Vaga(Quando la sintassi C17/C18 `[[fallthrough]]` sarà più comunemente 247b67aa4efSFederico Vagasupportata dai compilatori C, analizzatori statici, e dagli IDE, 248b67aa4efSFederico Vagaallora potremo usare quella sintassi per la pseudo parola chiave) 249b67aa4efSFederico Vaga 250b67aa4efSFederico VagaQuando la sintassi [[fallthrough]] sarà più comunemente supportata dai 251b67aa4efSFederico Vagacompilatori, analizzatori statici, e ambienti di sviluppo IDE, 252b67aa4efSFederico Vagaallora potremo usarla anche noi. 253b67aa4efSFederico Vaga 254b67aa4efSFederico VagaNe consegue che tutti i blocchi switch/case devono finire in uno dei seguenti 255b67aa4efSFederico Vagamodi: 256b67aa4efSFederico Vaga 257b67aa4efSFederico Vaga* ``break;`` 258b67aa4efSFederico Vaga* `fallthrough;`` 259b67aa4efSFederico Vaga* ``continue;`` 260b67aa4efSFederico Vaga* ``goto <label>;`` 261b67aa4efSFederico Vaga* ``return [expression];`` 262ac771142SFederico Vaga 263ac771142SFederico VagaArray di lunghezza zero o con un solo elemento 264ac771142SFederico Vaga---------------------------------------------- 265ac771142SFederico VagaAll'interno del kernel ricorre spesso la necessita di avere membri 266ac771142SFederico Vagadi dimensione variabile all'interno di una struttura dati. In questi 267ac771142SFederico Vagacasi il codice del kernel dovrebbe usare sempre i `"flexible array 268ac771142SFederico Vagamember" <https://en.wikipedia.org/wiki/Flexible_array_member>`_. La 269ac771142SFederico Vagatecnica degli array a lunghezza nulla o di un solo elemento non 270ac771142SFederico Vagadovrebbe essere più usata. 271ac771142SFederico Vaga 272ac771142SFederico VagaNel codice C più vecchio, la dichiarazione di un membro di dimensione 273ac771142SFederico Vagavariabile in coda ad una struttura dati veniva fatto dichiarando un 274ac771142SFederico Vagaarray di un solo elemento posizionato alla fine della struttura dati:: 275ac771142SFederico Vaga 276ac771142SFederico Vaga struct something { 277ac771142SFederico Vaga size_t count; 278ac771142SFederico Vaga struct foo items[1]; 279ac771142SFederico Vaga }; 280ac771142SFederico Vaga 281ac771142SFederico VagaQuesto ha portato ad un calcolo di sizeof() traballante (dovrebbe 282ac771142SFederico Vagarimuovere la dimensione del singolo elemento in coda per calcolare la 283ac771142SFederico Vagadimensione esatta dell' "intestazione"). Per evitare questi problemi è 284ac771142SFederico Vagastata introdotta un' `estensione a GNU C 285ac771142SFederico Vaga<https://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html>`_ che 286ac771142SFederico Vagapermettesse la dichiarazione di array a lungezza zero:: 287ac771142SFederico Vaga 288ac771142SFederico Vaga struct something { 289ac771142SFederico Vaga size_t count; 290ac771142SFederico Vaga struct foo items[0]; 291ac771142SFederico Vaga }; 292ac771142SFederico Vaga 293ac771142SFederico VagaMa questo ha portato nuovi problemi, e non ha risolto alcuni dei 294ac771142SFederico Vagaproblemi che affliggono entrambe le tecniche: per esempio 295ac771142SFederico Vagal'impossibilità di riconoscere se un array di quel tipo viene usato 296ac771142SFederico Vaganel mezzo di una struttura dati e _non_ alla fine (potrebbe accadere 297ac771142SFederico Vagasia direttamente, sia indirettamente quando si usano le unioni o le 298ac771142SFederico Vagastrutture di strutture). 299ac771142SFederico Vaga 300ac771142SFederico VagaLo standard C99 introduce i "flexible array members". Questi array non 301ac771142SFederico Vagahanno una dimensione nella loro dichiarazione:: 302ac771142SFederico Vaga 303ac771142SFederico Vaga struct something { 304ac771142SFederico Vaga size_t count; 305ac771142SFederico Vaga struct foo items[]; 306ac771142SFederico Vaga }; 307ac771142SFederico Vaga 308ac771142SFederico VagaQuesto è il modo con cui ci si aspetta che vengano dichiarati gli 309ac771142SFederico Vagaelementi di lunghezza variabile in coda alle strutture dati. Permette 310ac771142SFederico Vagaal compilatore di produrre errori quando gli array flessibili non si 311ac771142SFederico Vagatrovano alla fine della struttura dati, il che permette di prevenire 312ac771142SFederico Vagaalcuni tipi di bachi dovuti a `comportamenti inaspettati 313ac771142SFederico Vaga<https://git.kernel.org/linus/76497732932f15e7323dc805e8ea8dc11bb587cf>`_. 314ac771142SFederico VagaInoltre, permette al compilatore di analizzare correttamente le 315ac771142SFederico Vagadimensioni degli array (attraverso sizeof(), `CONFIG_FORTIFY_SOURCE`, 316ac771142SFederico Vagae `CONFIG_UBSAN_BOUNDS`). Per esempio, non esiste alcun meccanismo in 317ac771142SFederico Vagagrado di avvisarci che il seguente uso di sizeof() dia sempre come 318ac771142SFederico Vagazero come risultato:: 319ac771142SFederico Vaga 320ac771142SFederico Vaga struct something { 321ac771142SFederico Vaga size_t count; 322ac771142SFederico Vaga struct foo items[0]; 323ac771142SFederico Vaga }; 324ac771142SFederico Vaga 325ac771142SFederico Vaga struct something *instance; 326ac771142SFederico Vaga 327ac771142SFederico Vaga instance = kmalloc(struct_size(instance, items, count), GFP_KERNEL); 328ac771142SFederico Vaga instance->count = count; 329ac771142SFederico Vaga 330ac771142SFederico Vaga size = sizeof(instance->items) * instance->count; 331ac771142SFederico Vaga memcpy(instance->items, source, size); 332ac771142SFederico Vaga 333ac771142SFederico VagaIl valore di ``size`` nell'ultima riga sarà ``zero``, quando uno 334ac771142SFederico Vagainvece si aspetterebbe che il suo valore sia la dimensione totale in 335*c1f8e848SFederico Vagabyte dell'allocazione dinamica che abbiamo appena fatto per l'array 336ac771142SFederico Vaga``items``. Qui un paio di esempi reali del problema: `collegamento 1 337ac771142SFederico Vaga<https://git.kernel.org/linus/f2cd32a443da694ac4e28fbf4ac6f9d5cc63a539>`_, 338ac771142SFederico Vaga`collegamento 2 339ac771142SFederico Vaga<https://git.kernel.org/linus/ab91c2a89f86be2898cee208d492816ec238b2cf>`_. 340ac771142SFederico VagaInvece, `i flexible array members hanno un tipo incompleto, e quindi 341ac771142SFederico Vagasizeof() non può essere applicato 342ac771142SFederico Vaga<https://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html>`_; dunque ogni 343ac771142SFederico Vagauso scorretto di questo operatore verrà identificato immediatamente 344ac771142SFederico Vagadurante la compilazione. 345ac771142SFederico Vaga 346ac771142SFederico VagaPer quanto riguarda gli array di un solo elemento, bisogna essere 347ac771142SFederico Vagaconsapevoli che `questi array occupano almeno quanto lo spazio di un 348ac771142SFederico Vagasingolo oggetti dello stesso tipo 349ac771142SFederico Vaga<https://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html>`_, e quindi 350ac771142SFederico Vagacontribuiscono al calcolo della dimensione della struttura che li 351ac771142SFederico Vagacontiene. In questo caso è facile commettere errori quando si vuole 352ac771142SFederico Vagacalcolare la dimensione totale della memoria totale da allocare per 353ac771142SFederico Vagauna struttura dati:: 354ac771142SFederico Vaga 355ac771142SFederico Vaga struct something { 356ac771142SFederico Vaga size_t count; 357ac771142SFederico Vaga struct foo items[1]; 358ac771142SFederico Vaga }; 359ac771142SFederico Vaga 360ac771142SFederico Vaga struct something *instance; 361ac771142SFederico Vaga 362ac771142SFederico Vaga instance = kmalloc(struct_size(instance, items, count - 1), GFP_KERNEL); 363ac771142SFederico Vaga instance->count = count; 364ac771142SFederico Vaga 365ac771142SFederico Vaga size = sizeof(instance->items) * instance->count; 366ac771142SFederico Vaga memcpy(instance->items, source, size); 367ac771142SFederico Vaga 368ac771142SFederico VagaIn questo esempio ci siamo dovuti ricordare di usare ``count - 1`` in 369ac771142SFederico Vagastruct_size(), altrimenti avremmo --inavvertitamente-- allocato 370ac771142SFederico Vagamemoria per un oggetti ``items`` in più. Il modo più pulito e meno 371ac771142SFederico Vagapropenso agli errori è quello di usare i `flexible array member`, in 372ac771142SFederico Vagacombinazione con struct_size() e flex_array_size():: 373ac771142SFederico Vaga 374ac771142SFederico Vaga struct something { 375ac771142SFederico Vaga size_t count; 376ac771142SFederico Vaga struct foo items[]; 377ac771142SFederico Vaga }; 378ac771142SFederico Vaga 379ac771142SFederico Vaga struct something *instance; 380ac771142SFederico Vaga 381ac771142SFederico Vaga instance = kmalloc(struct_size(instance, items, count), GFP_KERNEL); 382ac771142SFederico Vaga instance->count = count; 383ac771142SFederico Vaga 384ac771142SFederico Vaga memcpy(instance->items, source, flex_array_size(instance, items, instance->count)); 385*c1f8e848SFederico Vaga 386*c1f8e848SFederico VagaCi sono due casi speciali dove è necessario usare la macro DECLARE_FLEX_ARRAY() 387*c1f8e848SFederico Vaga(da notare che la stessa macro è chiamata __DECLARE_FLEX_ARRAY() nei file di 388*c1f8e848SFederico Vagaintestazione UAPI). Uno è quando l'array flessibile è l'unico elemento di una 389*c1f8e848SFederico Vagastruttura, e l'altro è quando è parti un unione. Per motivi non tecnici, entrambi 390*c1f8e848SFederico Vagai casi d'uso non sono permessi dalla specifica C99. Per esempio, per 391*c1f8e848SFederico Vagaconvertire il seguente codice:: 392*c1f8e848SFederico Vaga 393*c1f8e848SFederico Vaga struct something { 394*c1f8e848SFederico Vaga ... 395*c1f8e848SFederico Vaga union { 396*c1f8e848SFederico Vaga struct type1 one[0]; 397*c1f8e848SFederico Vaga struct type2 two[0]; 398*c1f8e848SFederico Vaga }; 399*c1f8e848SFederico Vaga }; 400*c1f8e848SFederico Vaga 401*c1f8e848SFederico VagaLa macro di supporto dev'essere usata:: 402*c1f8e848SFederico Vaga 403*c1f8e848SFederico Vaga struct something { 404*c1f8e848SFederico Vaga ... 405*c1f8e848SFederico Vaga union { 406*c1f8e848SFederico Vaga DECLARE_FLEX_ARRAY(struct type1, one); 407*c1f8e848SFederico Vaga DECLARE_FLEX_ARRAY(struct type2, two); 408*c1f8e848SFederico Vaga }; 409*c1f8e848SFederico Vaga }; 410