Comprendre le comportement non défini d’un stream binary à l’aide de fseek (fichier, 0, SEEK_END) avec un fichier

La spécification C a une note de bas de page intéressante (n ° 268 C11dr §7.21.3 9)

“La définition de l’indicateur de position du fichier sur la fin du fichier, comme avec fseek(file, 0, SEEK_END) , a un comportement indéfini pour un stream binary (en raison de possibles caractères nuls de fin) ou pour tout stream avec un codage dépendant de l’état ne se termine certainement pas dans l’état de décalage initial “.

Est-ce que cela s’applique aux stream binarys lisant un fichier? (à partir d’un périphérique physique)

OMI, un fichier binary sur un disque est juste une mer d’octets. Il me semble qu’un fichier binary ne peut pas avoir de codage dépendant de l’état car c’est un fichier binary . Je suis flou sur le concept de “stream binarys à orientation large” et même si cela pourrait s’appliquer aux E / S de disque.

Je constate que l’appel de fseek(file, 0, SEEK_END) sur un stream série, tel qu’un port com, ou peut-être que stdin peut ne pas aboutir à la vraie fin car celle-ci n’a pas encore été déterminée. Ainsi, la question se réduit aux fichiers physiques.


[modifier] Réponse: Un problème avec les personnes âgées (peut-être jusqu’à la fin des années 1980). Actuellement en 2014, Windows, autres non-exotiques spécifiques à POSIT: pas un problème.

@Shafik Yaghmour fournit une bonne référence dans Utilisation de fseek et ftell pour déterminer la taille d’un fichier présentant une vulnérabilité? . Là, @Jerry Coffin décrit CP / M comme des fichiers binarys n’ayant pas toujours une longueur précise. (Enregistrements de 128 octets par wiki).

Merci à @ Keith Thompson pour la viande de la réponse.

Ensemble, cela explique le commentaire “(en raison des possibles caractères de fin possibles)”.

Les fichiers binarys vont être des séquences d’octets de 8 bits, avec une taille exacte spécifiée, sur tout système que vous êtes susceptible d’utiliser. Cependant, tous les systèmes ne stockent pas les fichiers de cette manière et la norme C est soigneusement conçue pour permettre la portabilité vers des systèmes présentant des caractéristiques inhabituelles.

Par exemple, une implémentation C conforme peut s’exécuter sur un système d’exploitation qui stocke des fichiers sous forme de séquences de blocs de 512 octets, sans indication du nombre d’octets significatifs du bloc final. Sur un tel système, lorsqu’un fichier binary est créé, le système d’exploitation peut remplir le rest du bloc final avec zéro octet. Lorsque vous lisez un tel fichier, les octets de remplissage peuvent apparaître dans l’entrée (même s’ils n’ont jamais été explicitement écrits dans le fichier) ou peuvent être ignorés (même si le programme qui a créé le fichier les a écrits explicitement) .

Si vous lisez à partir d’un stream non recherché (par exemple, une entrée au clavier), alors fseek(file, 0, SEEK_END) ne vous donnera pas simplement un résultat incorrect, il indiquera un échec en renvoyant un résultat différent de zéro. (Sur les systèmes compatibles POSIX, il renvoie -1 et définit errno ; ISO C ne l’exige pas.)

Sur la plupart des systèmes, fseek(file, 0, SEEK_END) sur un fichier binary recherchera la fin réelle du fichier (une position déterminée par le nombre d’octets exactement écrits dans le fichier) ou renverra une indication d’échec en clair. Si vous utilisez quand même des fonctionnalités spécifiques à POSIX, vous pouvez assumer ce problème en toute sécurité. vous pouvez probablement faire la même hypothèse pour Windows et un certain nombre d’autres systèmes. Si vous voulez que votre code soit 100% portable sur des systèmes exotiques, vous ne devez pas supposer que les fichiers binarys ne seront pas complétés avec des octets supplémentaires.