Fausse carte d'identité > Articles > Des numéros de téléphone factices qui ne peuvent pas exister : un défaut de 12 % caché dans un seul appel `mt_rand`

Des numéros de téléphone factices qui ne peuvent pas exister : un défaut de 12 % caché dans un seul appel mt_rand

Environ un sur huit des numéros de téléphone américains et canadiens que notre générateur produisait ne pouvaient pas exister. Non pas « avaient l'air bizarre » — ne pouvaient pas exister, au sens où le North American Numbering Plan les interdit et où n'importe quel validateur que vous voudrez nommer les rejette au premier coup d'œil.

La première ligne du fichier cached/en_US/phone.txt déployé était +12121007909. Indicatif 212, Manhattan, parfaitement réel. Puis le code de central : 100. Il n'existe aucun central 100 à Manhattan ni ailleurs, et il ne pourra jamais en exister.

La cause tenait à un seul appel à mt_rand(1, 9).

Ce qui mérite d'être raconté ici, ce n'est pas le défaut. C'est que le correctif évident aurait été pire que le bug, pour une raison qui n'a rien à voir avec les numéros de téléphone — et que le corriger proprement nous a obligés à poser une question que nous évitions : celle de savoir s'il est seulement judicieux de générer des numéros de téléphone plausibles.

La règle qui a été enfreinte

Un numéro nord-américain s'écrit NPA-NXX-XXXX. NPA est l'indicatif régional, NXX le code de central, XXXX la ligne d'abonné.

Deux contraintes s'appliquent à NXX, auxquelles presque personne ne pense :

  • Le premier chiffre doit être compris entre 2 et 9. Un 0 ou un 1 en tête est structurellement impossible, car 0 et 1 sont les préfixes de l'opérateur et de l'interurbain. Un central commençant par l'un ou l'autre serait injoignable par construction.
  • Les codes N11 sont réservés. 211, 311, 411, 511, 611, 711, 811, 911 sont des codes de service et ne sont jamais attribués à des abonnés.

Il existe une troisième convention : 555 est le central fictif réservé, celui qu'utilise tout film américain. Le plan de numérotation ne l'interdit pas comme il interdit 1XX, mais il est mis de côté, et un numéro qui en relève est reconnaissable comme faux par quiconque a déjà regardé la télévision.

Notre générateur choisissait un indicatif régional réel dans une table, puis remplissait les sept chiffres restants :

$num .= (string) mt_rand(1, 9);                    // first subscriber digit: not 0
for ($i = 1; $i < $rest; $i++) $num .= (string) mt_rand(0, 9);

Le commentaire explique l'intention : ne jamais commencer par 0. L'intention est juste pour la mauvaise raison, et elle s'arrête un chiffre trop tôt. mt_rand(1, 9) exclut 0 et admet 1 — précisément le chiffre que le NANP interdit lui aussi. Un neuvième de tous les numéros nord-américains que le site avait produits depuis toujours naissait invalide.

Ce que cela mesurait réellement

Mesure effectuée sur les fichiers de données déployés, environ 20 000 numéros par locale, le 18 juillet 2026 :

LocaleNumérosNXX commence par 1Code de service N11555Total invalide
en_US19 9992 233 (11,17 %)190 (0,95 %)302 423 (12,12 %)
en_CA20 0002 229 (11,14 %)184 (0,92 %)182 413 (12,06 %)
fr_CA19 9982 222 (11,11 %)178 (0,89 %)242 400 (12,00 %)

Les trois lignes concordent parce que le défaut est dans l'algorithme, pas dans les données — toutes les locales NANP partagent le même chemin de code et donc le même taux d'échec. Simuler à nouveau l'algorithme d'avant le correctif sur 200 000 numéros par locale le reproduit à deux décimales près : 11,02 % de 1 en tête, 0,99 % de N11, 0,11 % de 555, 12,03 % en union.

La valeur théorique tranche la question. NXX est tiré parmi 900 combinaisons équiprobables (premier chiffre de 1 à 9, les deux autres de 0 à 9) :

  • 100 d'entre elles commencent par 1 → 11,111 %
  • 9 d'entre elles sont des N11 → 1,000 %, mais 111 est déjà compté ci-dessus, elles n'en ajoutent donc que 8 nouvelles
  • 555 en ajoute 1 de plus

(100 + 8 + 1) / 900 = 12.111%. Ce n'est pas la somme des colonnes — les colonnes se recouvrent, et les additionner est la façon d'obtenir un total faux qui a pourtant l'air à peu près juste.

C'est déjà un petit avertissement en soi. Un commentaire dans le code décrivant ce défaut annonçait 11,9 %, obtenus en additionnant des composantes arrondies qui partagent un élément. Le chiffre exact est 12,1 %. Personne n'aurait jamais repéré cela à la lecture, car 11,9 % et 12,1 % sont également plausibles. Les chiffres dans les commentaires sont des affirmations non vérifiées déguisées en documentation — un point que nous avons longuement développé dans Un test qui ne peut pas échouer, avant de le démontrer aussitôt sur nous-mêmes.

Pourquoi le correctif évident est le mauvais correctif

La réparation naturelle est une boucle de rejet :

do {
    $nxx = generate_nxx();
} while (!nanp_valid($nxx));

Trois lignes, une sortie parfaitement uniforme sur l'espace valide — et cela aurait cassé le site.

La garantie centrale de notre générateur est qu'une URL est un permalien. La fiche située à une adresse donnée est dérivée en hachant le sel secret du site avec l'id ; le résultat initialise le PRNG, après quoi chaque champ est tiré d'un seul flux déterministe — prénom, nom de famille, ville, rue, code postal, employeur, téléphone. Le hachage exact, sa troncature et le secret lui-même ne sont délibérément pas publiés ici. La même URL donne la même personne aujourd'hui, l'an prochain, et sur un serveur reconstruit.

Cette garantie a une conséquence fragile : le flux est positionnel. Le champ n reçoit ce que mt_rand renvoie à la position n. Si un champ antérieur consomme un nombre de tirages différent de celui qu'il consommait auparavant, tous les champs suivants se décalent, et la fiche change complètement.

Une boucle de rejet consomme un nombre de tirages dépendant des données. La plupart des numéros passent du premier coup ; environ un sur huit en demande un deuxième ; parfois un troisième. Le compte dépend des valeurs tirées, qui dépendent de la graine. Ainsi, pour à peu près une fiche sur huit, le champ téléphone consommerait un tirage supplémentaire, et tout ce qui le suit dans le flux se déplacerait.

Le résultat visible par l'utilisateur n'est pas « quelques numéros de téléphone ont changé ». C'est qu'un permalien sur huit renvoie désormais à une personne entièrement différente — autre nom, autre ville, autre employeur — parce qu'un numéro de téléphone situé trois champs en amont a consommé un tirage aléatoire de plus qu'auparavant.

C'est le même invariant que protègent les fonctions de sélection avec mt_srand($keep), et celui-là même autour duquel les tests de mutation ont été construits. La justesse du champ téléphone vaut beaucoup. Elle ne vaut pas le permalien.

Le correctif : réparer les chiffres, pas le tirage

La contrainte est donc posée avant même de commencer : le nombre d'appels à mt_rand ne doit pas dépendre de ce qu'ils renvoient. Cela exclut le rejet, et cela exclut tout tirage supplémentaire conditionnel.

Ce qui reste, c'est de réparer les chiffres déjà en main :

if ($cc === '1' && $rest >= 7) {
    $npa = substr($num, 0, 3);          // area code, from the prefix table
    $nxx = substr($num, 3, 3);          // central office code
    $sub = substr($num, 6);             // 4 subscriber digits

    if ($nxx[0] === '1') $nxx[0] = '2';                    // N must be 2-9
    if ($nxx[1] === '1' && $nxx[2] === '1') $nxx[2] = '0';  // not N11
    if ($nxx === '555') $nxx = '554';                       // 555 is reserved

    $num = $npa . $nxx . $sub;
}

Aucune branche ne tire. Le nombre de tirages est constant pour toute entrée, si bien que le flux atterrit à une position identique, que le numéro ait eu besoin d'être réparé ou non. Relancer la mesure après le correctif donne 0.00% d'invalides dans les trois locales, et le contrôle de déterminisme renvoie toujours des numéros identiques pour des graines identiques.

Le coût est honnête et doit être dit : la distribution de sortie n'est plus uniforme. Chaque central 1XX se rabat sur le 2XX correspondant, si bien que les codes 2XX apparaissent environ deux fois plus souvent que 3XX à 9XX. Les codes N11 se replient sur N10, et 555 sur 554. Cela biaise environ 12 % des numéros vers des centraux voisins.

Est-ce acceptable ? Pour cette application, oui, et la raison mérite d'être formulée avec précision. Personne n'inspecte la distribution des codes de central sur un corpus d'identités factices. Tout le monde remarque un numéro de téléphone qu'un formulaire d'inscription refuse. Le biais est invisible ; l'invalidité ne l'était pas. Si le champ avait alimenté un modèle statistique plutôt qu'une fiche d'affichage, l'arbitrage aurait basculé dans l'autre sens — et il aurait fallu résoudre le problème du déterminisme autrement, probablement en dotant le champ téléphone d'un flux propre, initialisé indépendamment, pour que son nombre de tirages puisse varier sans perturber quoi que ce soit en aval.

Cette option était disponible et nous ne l'avons pas prise, parce qu'elle coûte un second chemin d'initialisation dans chaque champ qui pourrait un jour en avoir besoin. Consigner pourquoi un correctif moins coûteux a été retenu est plus utile que de consigner le correctif.

Le même audit a trouvé deux choses plus petites

Des indicatifs régionaux en double. La liste de préfixes fr_CA contenait onze entrées, mais 367 et 438 y figuraient chacun deux fois :

'fr_CA' => ['1', ['514','438','450','579','418','367','581','819','873','367','438'], 10],

La sélection se fait par mt_rand(0, count - 1) sur la liste brute, si bien que ces deux codes sortaient à 18,18 % chacun contre 9,09 % pour les sept autres. Rien d'invalide n'était produit ; le Québec avait simplement deux villes deux fois plus peuplées que ne le dit le plan de numérotation. Le correctif est array_unique au moment de la sélection, ce qui maintient le nombre de tirages à un et ne perturbe rien. Sur l'ensemble des 65 entrées de locale, la table contient 959 préfixes, dont 957 sont distincts — ces deux doublons étaient les seuls de toute la table.

Une restriction appliquée bien trop largement. La règle mt_rand(1, 9) — le premier chiffre d'abonné n'est jamais 0 — s'applique à toutes les locales, justifiée par le commentaire « sinon le numéro ressemblerait à un numéro au format national avec un zéro initial ». Ce raisonnement est faux. Le zéro initial du format national se place avant le préfixe (07… au Royaume-Uni, 06… aux Pays-Bas), et non à l'intérieur de la partie abonné. Dans la plupart des pays, 0 y est un chiffre parfaitement légal.

L'effet est que 10 % de l'espace de génération est jeté sans raison, dans 62 locales où la règle ne sert à rien. Dans les trois locales NANP, la règle est utile par accident — elle bloque les centraux 0XX — mais elle est aussi la raison pour laquelle le vrai problème est resté caché, car elle donne l'impression que la question du chiffre initial a déjà été traitée. Une règle à moitié juste au seul endroit où elle compte est un bon déguisement pour une règle fausse partout ailleurs.

Un audit qui ne trouve rien est aussi un résultat

Tout ce qui précède est un défaut. Cela donne une impression trompeuse de ce qu'est l'audit d'une table de données ; il vaut donc la peine de rapporter le résultat inverse avec la même ampleur.

Nous avons contrôlé le Danemark, la Suède et la Norvège face aux documents de numérotation primaires de leurs régulateurs — chaque préfixe, chaque longueur de numéro, chaque exclusion. Le résultat : aucune correction obligatoire. Les préfixes étaient bons, les longueurs étaient bonnes, les omissions délibérées étaient bonnes. Le seul changement, où que ce soit, a porté sur deux préfixes danois, 24 et 25, désormais présents, qui portent la liste danoise à 26 entrées.

Mettez cela en regard du cas nord-américain, dans la même base de code. Là-bas, une ligne de code produisait un taux de défaut de 12 % sur trois locales. Ici, un contrôle soigneux face aux sources primaires a confirmé que la table était déjà correcte. Les deux audits ont coûté à peu près le même effort, et un seul a produit un constat.

Cela compte à cause d'un biais qui s'installe vite : si chaque audit que vous rédigez a trouvé quelque chose, vous finissez par croire qu'un audit qui ne trouve rien a été mal mené. Il ne l'a pas été. Un résultat propre est une information — il transforme une hypothèse en fait contrôlé, et c'est ce fait contrôlé qui vous permet de cesser de réexaminer les préfixes danois chaque fois qu'un bug de téléphone apparaît ailleurs. Les lignes norvégienne et suédoise de notre table étaient auparavant supposées correctes. Elles sont désormais connues comme correctes, et c'est un état différent et meilleur, quand bien même pas un seul caractère n'a changé.

Cela a également liquidé un mythe précis. On répète largement que les numéros de mobile suédois ont une longueur variable. C'est faux. La table de la PTS donne, pour chacun des préfixes 70, 72, 73, 76 et 79, un maximum égal au minimum, égal à 9 chiffres. La confusion vient des numéros géographiques suédois, qui varient bel et bien entre 7 et 9 chiffres. Nos données avaient depuis toujours la bonne longueur fixe — mais avant le contrôle, avoir raison et répéter une rumeur étaient indiscernables de l'intérieur.

La même table, deux fiabilités

Le plan danois a fait apparaître quelque chose qui n'a aucun équivalent dans le NANP et qui change ce à quoi la table de préfixes peut servir.

Le document danois réserve des plages à l'usage mobile avec le mot fortrinsvisprincipalement, et non exclusivement : « Nummerserier, der er fortrinsvis afsat til mobilkommunikation ». Conséquence : à l'intérieur des plages formellement attribuées au fixe, il existe environ 90 sous-séries à trois chiffres délivrées pour un service mobile — 342, 344349, 431, 627, 771772 et d'autres. Et la portabilité des numéros est totale au Danemark : le préfixe d'un numéro réel vous dit de quel bloc il a été tiré à l'origine et absolument rien sur qui l'exploite aujourd'hui ni sur quelle technologie.

Remarquez maintenant que cela affecte de façon totalement différente les deux sens d'utilisation :

Sens d'utilisationCe que la table de préfixes vous donneFiabilité
Génération — produire un numéro de mobile danois plausibleTout ce qui est tiré de ces plages est légitimement mobileCorrect. Les plages sont mobiles par attribution ; c'est tout ce qu'exige la génération.
Classification — décider si un numéro réel donné est mobileUne supposition fondée sur le bloc d'origine, mise en échec par les ~90 sous-séries mobiles dans des plages fixes et par la portabilitéPurement heuristique.

La même table, les mêmes données, une fiabilité opposée selon le sens dans lequel on la fait tourner. L'erreur est facile, car une table qui a été validée face à un régulateur donne le sentiment d'être validée pour tous les usages, ce qu'elle n'est pas. La nôtre est validée pour le sens dans lequel nous l'utilisons — et si quelqu'un s'en saisit un jour pour répondre à « le numéro de ce client est-il un mobile ? », elle produira des réponses assurées, plausibles et souvent fausses.

Les règles structurelles du NANP qui ouvraient cet article n'ont pas cette propriété : NXX ne peut pas commencer par 1, et cela vaut dans les deux sens, pour toujours. Il est facile de généraliser à partir d'une telle règle et d'en conclure que les plans de numérotation sont nets. La plupart ne le sont pas. Le Danemark dit principalement, et un adverbe dans le document d'un régulateur fait la différence entre un fait et une estimation.

La question sous-jacente : à qui appartient ce numéro ?

Corriger la validité structurelle rend les numéros mieux formés. Cela ne change rien à une propriété plus dérangeante, que le même audit a quantifiée.

Nous générons à partir de préfixes d'opérateurs réels et actifs — de véritables plages mobiles, choisies délibérément parce qu'elles sont à jour et que, contrairement aux indicatifs du fixe, elles ne sont pas liées à une ville qu'il faudrait ensuite maintenir cohérente. Conséquence : nous générons exactement là où vivent les abonnés. Un numéro généré n'est pas un numéro qui ressemble à un vrai. Il peut tout simplement en être un.

Avec quelle probabilité ? Cela dépend entièrement de la taille de l'espace de numérotation du pays par rapport à sa population :

LocaleEspace de générationLocaleEspace de génération
is_IS1 350 000en_GB450 000 000
me_ME8 100 000ru_RU576 000 000
lv_LV9 000 000bn_BD630 000 000
hy_AM10 800 000pt_BR1 350 000 000
ka_GE10 800 000de_DE1 530 000 000
ro_MD11 700 000zh_CN2 700 000 000
sl_SI11 700 000id_ID3 060 000 000
no_NO14 400 000en_IN3 600 000 000

L'Islande est de loin le pire cas. Le générateur peut produire 1 350 000 numéros islandais distincts. L'Islande compte environ 390 000 habitants et à peu près autant d'abonnements mobiles actifs. Quelque chose comme un numéro islandais généré sur trois ou quatre appartient à une personne réelle. Le Monténégro, la Moldavie, la Lettonie, la Slovénie, l'Arménie et la Géorgie se situent tous dans la même fourchette.

Les grands pays s'en sortent mieux, mais jamais proprement. L'espace de 450 000 000 de numéros du Royaume-Uni face à environ 80 000 000 de mobiles actifs signifie encore qu'environ 18 % des numéros britanniques générés sont en service.

Ce n'est pas un bug. C'est la conséquence directe et inévitable du choix de conception « préfixe réel plus queue aléatoire », et aucun soin apporté à la queue n'y change quoi que ce soit.

Ce que les régulateurs réservent réellement — et ce que nous n'avons pas pu confirmer

Plusieurs pays réservent des blocs précisément pour que les films, les manuels et les données de test disposent d'un endroit sûr où pointer. Nous sommes partis les chercher, et le résultat honnête est une liste bien plus courte que prévu, assortie d'une leçon sur ce que vaut un « nous n'avons rien trouvé ».

Confirmé à partir de documents primaires de régulateurs présents sur disque :

PaysPlage réservéeTailleSource
FranceRacines 01 99 00, 02 61 91, 03 53 01, 04 65 71, 05 36 49, 06 39 986 × 10 000 = 60 000Plan de numérotation de l'ARCEP, annexe 2 à la décision 2018-0881
Irlande089 011 0000089 011 0999 (mobile)1 000ComReg 15/136r4
IrlandeIndicatif 020, numéro d'abonné à 7 chiffres, entièrement « réservé aux besoins de la fiction »10 000 000ComReg 15/136r1
Norvège680 50000680 59999, statut BLOKKERT, pour la production de télévision et de cinéma10 000Plan de numérotation de Nkom
Royaume-Uni07700 90000007700 900999 (mobile)1 000Ofcom, Telephone numbers for use in TV and radio drama programmes, rév. 03.2019
Allemagne0171 3920000…099, 0176 04069000…099, plus une poignée de numéros Vodafone isolés~200BNetzA, Rufnummern für Medienproduktionen, Mitteilung 148/2021
Suède070 1740605070 174069995PTS, Telefonnummer till böcker och filmer, décision 09.2020
Australie~30 numéros listés individuellement dans 0491 5xx~30ACMA, Phone numbers for use in TV shows, films and creative works

L'entrée norvégienne est la ligne la plus instructive de cette table, parce qu'elle nous est inutile. Le bloc se situe dans la plage 68, qui relève du fixe. Les numéros de mobile norvégiens sont en 4x et 9x, et notre liste de préfixes no_NO compte seize entrées, dont exactement zéro commence par 6. Le générateur ne peut donc pas utiliser le bloc norvégien réservé à la fiction — et, pour la même raison, ne peut pas non plus s'y égarer par accident. La formulation de Nkom est sans ambiguïté (« Numrene i serien skal ikke brukes til ordinær bruk »), la réservation est réelle, et elle est totalement inapplicable au champ que nous générons.

Cela mérite d'être énoncé comme un principe général, car « le pays X réserve-t-il des numéros fictifs ? » est la mauvaise question. La bonne est : « le pays X réserve-t-il des numéros fictifs dans la plage à partir de laquelle je génère ? » Un bloc de fixe réservé n'est d'aucun secours à un générateur de mobiles, et un bloc de mobile réservé n'est d'aucun secours à qui génère des numéros fixes. La moitié de la valeur de la table ci-dessus tient aux discordances.

Deux autres entrées nous ont surpris. La France réserve six racines, une par zone géographique plus le mobile — nous en attendions deux, celles que citent les billets de blog. Et l'Irlande, pays de cinq millions d'habitants, a mis de côté un indicatif entier de dix millions de numéros pour la fiction, à côté de son petit bloc mobile. Le bloc mobile est cité partout ; l'attribution 020 n'est citée nulle part.

Impossible à confirmer à partir d'une source en notre possession :

Affirmation que nous ne pouvions pas assumerStatut
Royaume-Uni : 01632 960xxx comme seconde plage de fictionZéro occurrence dans le moindre document de régulateur. Largement repris en ligne ; la page Ofcom que nous détenons ne couvre que le bloc mobile 07700 900.
Corée du Sud : 010-3348-xxxx et 010-6687-xxxx comme centraux réservésUn mythe, et le plus lourd de conséquences de cette liste — voir ci-dessous.
Pays-Bas, Brésil, Inde, Islande, Finlande, Lettonie : « pas de plage réservée »Nous n'avons de constat ni dans un sens ni dans l'autre. C'est une absence de preuve.
Danemark : « pas de plage réservée »Contrôlé face au plan de numérotation et absent de celui-ci. C'est plus faible qu'il n'y paraît : une réservation faite par une décision réglementaire distincte, hors du plan, serait invisible pour cette recherche. À consigner comme « absent du plan de numérotation », et non comme « absence prouvée ».

Et une affirmation que nous avons dû rétrograder après l'avoir contrôlée correctement. Nous avions consigné le Japon et l'Afrique du Sud comme des confirmations solides de « pas de plage réservée ». Une seule survit.

Pour le Japon, nous détenons les tables d'attribution de blocs du ministère des Affaires intérieures et des Communications (état au 1er septembre 2024) pour les plages 060, 070, 080 et 090. Chaque bloc à cinq chiffres de 09010 à 09099 est attribué à un opérateur nommé — NTT docomo, KDDI, SoftBank, Okinawa Cellular — sans aucun bloc marqué comme destiné à la fiction, aux tests, à un usage fictif ou tenu en réserve. C'est un résultat négatif véritablement solide : les tables sont exhaustives par construction, si bien qu'une catégorie non listée devrait apparaître comme un trou, et il n'y en a aucun.

Pour l'Afrique du Sud, notre source ICASA est un PDF du Government Gazette dont l'extraction a donné du binaire largement illisible. Il contient zéro occurrence de « reserved », « drama », « film » ou « test » — et ce zéro ne signifie absolument rien, car un fichier corrompu renvoie zéro correspondance pour n'importe quelle chaîne, y compris celles qu'il contient à coup sûr. Nous avions misé une conclusion sur une recherche qui ne pouvait pas aboutir.

Ce mode de défaillance s'est déjà retourné contre nous, dans une partie complètement différente du système, et il fait l'objet d'un article à lui seul : Le contrôle qui devient aveugle exactement là où vous en avez besoin. En résumé, une recherche qui renvoie « rien trouvé » signale l'une de deux choses très différentes — la chaîne est absente, ou la recherche était incapable — et la sortie est identique dans les deux cas.

Le bloc coréen qui n'existe pas

Une « réservation » largement reprise s'est révélée pire qu'inutile, et c'est la plus forte illustration, dans tout cet article, de ce qui fait que la plage compte plus que la réservation.

L'article Fictitious telephone number de Wikipédia présente 010-3348-xxxx et 010-6687-xxxx comme les numéros de fiction de la Corée du Sud. La source primaire dit autre chose. Le Korean Film Council (KOFIC) détient six lignes au total — quatre fixes, deux mobiles — pour la production cinématographique, et il ne publie délibérément que l'indicatif et le central (국번), et non les numéros complets, précisément pour qu'ils ne soient pas utilisés n'importe comment. Ce qui existe, ce sont donc deux lignes d'abonné précises, et non un bloc de dix mille.

Générer une queue aléatoire de quatre chiffres à l'intérieur du central 3348 ne permettrait donc pas d'éviter les abonnés actifs. Cela les viserait : chaque fiche coréenne serait concentrée sur un central où 9 998 des 10 000 numéros appartiennent à des personnes réelles. Un « correctif » bâti sur cette citation rend strictement pire le problème qu'il prétend résoudre, et il a l'air responsable en le faisant.

La règle générale que cela enseigne est plus étroite que « contrôlez vos sources » : une réservation citée comme une plage, alors que le document primaire réserve des numéros individuels, n'est pas une plage. Les deux s'écrivent presque à l'identique dans les sources secondaires.

La table ci-dessus comporte donc trois niveaux, et les niveaux comptent plus que les lignes : confirmé par un document que nous pouvons citer, supposé mais non documenté, et non investigué. Seul le premier niveau permet de construire sans risque.

Le dilemme, et les trois locales où il a une réponse

Supposons que nous passions aux plages réservées partout où elles existent. Voyez ce que cela implique.

La réservation allemande porte sur environ 200 numéros. La locale allemande génère des fiches sans limite. Bien avant d'avoir regardé quelques milliers d'identités allemandes, les numéros de téléphone se mettraient à se répéter — et à se répéter de façon immédiatement visible, puisqu'ils partagent tous une poignée de préfixes. Le champ passerait de « plausible, parfois réel » à « manifestement synthétique, et seulement deux cents possibilités ». Le bloc suédois compte 95 numéros ; celui de l'Australie est une liste d'environ trente numéros nommés un à un, le reste du central environnant étant en service.

Il ne suffit donc pas que la réservation soit réelle. Trois conditions doivent tenir ensemble : la plage réservée doit se trouver dans la bande mobile à partir de laquelle nous générons, elle doit être assez vaste pour qu'un jeu de fiches ne se répète pas visiblement, et elle ne doit pas être un marqueur culturel — le 555-01xx américain est sûr, et tout lecteur américain y reconnaît instantanément « un numéro de film », ce qui échange une forme de fausseté contre une autre.

Exactement trois locales satisfont les trois conditions : en_GB (le 07700 900xxx d'Ofcom), en_IE (le 089 011 0xxx de ComReg) et fr_FR (la racine 06 39 98 de l'ARCEP). Pour ces trois-là, la probabilité qu'un numéro généré appartienne à une personne vivante est désormais nulle, et non plus « plus faible » — et pour la France, c'est le plus grand gain isolé disponible dans tout l'ensemble, puisque environ 40 % des numéros français étaient ceux de quelqu'un avant le changement, contre 18 % pour le Royaume-Uni.

Le coût est visible et mérite d'être énoncé. La réserve utilisable est de 900 numéros pour le Royaume-Uni et l'Irlande, et de 9 000 pour la France — le sous-bloc se terminant par …000…099 est inatteignable, parce que le premier chiffre d'abonné est toujours compris entre 1 et 9. Dans un jeu de 200 fiches britanniques, environ 26 numéros de téléphone se répètent. C'est le prix de la garantie, et il est payé précisément dans les pays dont les régulateurs se sont donné la peine d'aider, ce qui reste un résultat pervers même lorsqu'on l'accepte.

Et cela règle 3 locales sur 65. Les 62 autres sont inchangées, y compris tous les cas que la première moitié de cet article qualifiait d'urgents :

  • L'Islande — le pire cas de toute la table — ne peut pas être réglée. Il n'existe aucune plage réservée dans le plan islandais, et la seule voie théorique (générer à partir de blocs jamais délivrés à un opérateur) exige des données d'attribution que personne ne publie pour l'Islande.
  • La Corée du Sud et le Japon ne peuvent pas non plus être réglés, pour les deux raisons distinctes exposées plus haut : la Corée réserve des lignes individuelles plutôt qu'un bloc, et les tables d'attribution japonaises ne laissent aucune catégorie non attribuée à utiliser.
  • Le Monténégro, la Moldavie, la Lettonie, la Slovénie, l'Arménie et la Géorgie se situent au même ordre de risque que l'Islande et reçoivent la même non-réponse.

Voilà la forme honnête du résultat : non pas « résolu », mais la frontière du soluble a été trouvée et tout ce qui se situe à l'intérieur a été fait. Les options restantes sont toujours les mêmes compromis, et elles sont toujours ouvertes :

  • Des plages réservées partout où il en existe une — rejeté : cela mettrait l'Allemagne à 200 numéros, la Suède à 95, l'Australie à 30, et 555-01xx dans les trois locales les plus lues.
  • Des plages en service partout, comme auparavant — variété maximale, et un abonné islandais réel derrière une large minorité de fiches islandaises.
  • Des centraux structurellement valides mais délibérément non attribués — des codes de central qui existent dans le plan mais ne sont attribués à aucun opérateur. Cela demande des données d'attribution pays par pays dont nous ne disposons pas, et les attributions changent.

Le reste du travail était la partie sans ambiguïté : rendre les numéros structurellement valides, supprimer les préfixes en double, et consigner les chiffres de collision pour que l'arbitrage soit une décision que quelqu'un peut prendre plutôt qu'une propriété que personne n'a mesurée.

La liste de contrôle

  1. Connaissez les règles structurelles de ce que vous falsifiez. « Ça ressemble à un numéro de téléphone » n'est pas une spécification. Le NANP impose trois contraintes sur un seul champ ; nous n'avions implémenté que la moitié de l'une d'elles.
  2. Quand la sortie doit être déterministe, le nombre de tirages aléatoires ne doit pas dépendre des valeurs tirées. Cela exclut l'échantillonnage par rejet, les boucles de réessai et tout tirage supplémentaire conditionnel — et ce n'est pas évident tant qu'on ne s'y est pas fait prendre.
  3. Préférez réparer les valeurs tirées plutôt que de les tirer à nouveau. La réparation a un coût constant. Le prix est un biais de distribution, qui est en général ce qu'il est le moins coûteux de perdre.
  4. Consignez ce que coûte le correctif. « Environ 12 % des numéros glissent vers un central voisin » est un fait dont la personne suivante a besoin. Un correctif silencieux la laisse redécouvrir le biais et le traiter comme un nouveau bug.
  5. N'additionnez pas des pourcentages arrondis qui se recouvrent. Les nôtres donnaient 11,9 % là où l'union vaut 12,1 %. Calculez l'union directement, ou énoncez les composantes séparément.
  6. Contrôlez vos tables de correspondance pour y détecter les doublons. Deux entrées répétées sur 959 donnaient à deux indicatifs canadiens le double du poids de leurs voisins, et rien dans la sortie n'avait l'air faux.
  7. Méfiez-vous d'une justification juste pour la mauvaise raison. « Ne jamais commencer par 0 » était correct par accident dans trois locales, faux dans soixante-deux, et cela a camouflé le vrai défaut pendant toute la vie du champ.
  8. Séparez « nous avons confirmé qu'il n'y en a pas » de « nous n'en avons pas trouvé ». Les deux se lisent pareil dans un résumé et n'ont pas du tout la même valeur.
  9. Une recherche sans résultat sur un fichier illisible n'est pas une preuve. Vérifiez que la recherche aurait pu aboutir — cherchez dans le fichier corrompu une chaîne dont vous savez qu'elle s'y trouve, avant de croire un résultat négatif.
  10. Demandez-vous si une plage réservée est réservée dans votre plage. La Norvège réserve un bloc de fiction que notre générateur de mobiles ne peut ni utiliser ni atteindre par accident. L'existence d'une réservation n'est pas son applicabilité.
  11. Lisez les adverbes du régulateur. Le Danemark attribue des plages « principalement » au mobile. Ce seul mot signifie que la table est fiable pour générer des numéros et non fiable pour les classer.
  12. Consignez les audits propres comme des constats. « Contrôlé, rien d'anormal » transforme une hypothèse en fait et évite à la personne suivante de le recontrôler. Un audit ne se juge pas au fait d'avoir trouvé quelque chose.
  13. Contrôlez si une « plage réservée » est bien une plage. La Corée réserve six lignes individuelles et n'en publie que le central. Citée de seconde main, la chose se lit comme un bloc de dix mille, et bâtir sur cette lecture aurait dirigé chaque fiche coréenne vers des abonnés actifs.
  14. Mesurez les répétitions qu'achète une petite réserve avant de la prendre. 900 numéros utilisables, cela fait environ 26 répétitions sur 200 fiches. C'est un chiffre à accepter délibérément, pas à découvrir sur une capture d'écran.

Il a suffi d'une ligne pour causer le défaut lui-même, et il en a fallu huit pour le corriger. Tout ce qu'il avait de coûteux se trouvait en aval : le correctif inutilisable, l'invariant qui le rendait inutilisable, et la question — toujours ouverte — de savoir si un numéro de téléphone susceptible de faire sonner une personne réelle à Reykjavík a seulement sa place sur une page de gens inventés.

Sur le chemin d'initialisation et l'invariant de flux sur lesquels cet article ne cesse de buter, voir Comment fonctionne notre générateur. Sur la suite de tests propre à cet invariant et sur la manière dont nous avons établi qu'elle était capable d'échouer, voir Un test qui ne peut pas échouer. Sur d'autres défauts que nous avons trouvés en comptant plutôt qu'en regardant, voir Ce que nous avons mal compris.


Données arrêtées au 2026-07-18

Les mesures du défaut ont été prises le 18 juillet 2026, sur share/name_gen/ng_phone.php tel que livré dans source_share_1.1.7 et sur les fichiers cached/<locale>/phone.txt déployés. La recherche sur les régulateurs, le passage aux plages réservées pour en_GB, en_IE et fr_FR, ainsi que les chiffres de répétition, ont été réalisés le 21 juillet 2026 sur share 1.1.8.

⚠ Les plages réservées constituent une modification des données de numérotation ; les jeux de données cached/<locale>/phone.txt déployés sont reconstruits de façon centralisée, si bien que les trois locales portent les anciens numéros issus des plages en service jusqu'à ce que cette reconstruction s'exécute.

Sources et remarques :

  • Les taux de défaut — mesurés sur les données déployées, ~20 000 numéros par locale : en_US 2 423 invalides sur 19 999 (12,12 %), en_CA 2 413 sur 20 000 (12,06 %), fr_CA 2 400 sur 19 998 (12,00 %). Reproduits indépendamment en simulant à nouveau l'algorithme d'avant le correctif sur 200 000 numéros par locale, ce qui donne 12,03 % en union dans les trois cas. La valeur théorique est (100 + 8 + 1) / 900 = 12.111%.
  • ⚠ Un chiffre de la source est faux. Le commentaire explicatif de ng_phone.php donne le taux combiné comme 11,9 %, obtenu en additionnant 11.00% + 0.90% + 0.11%. Ces composantes se recouvrent — 111 satisfait à la fois la condition du 1 en tête et la condition N11 — elles ne peuvent donc pas être additionnées, et l'addition n'atteint même pas le total qu'elle annonce (elle donne 12,01 %). L'union correcte vaut 12,1 %. Cet article utilise les chiffres mesurés et théoriques ; le commentaire n'a pas été corrigé.
  • Le correctifng_phone.php, lignes 173–183. La mesure après correctif renvoie 0,00 % d'invalides pour les trois locales NANP, et mt_srand(7) exécuté deux fois de suite renvoie le même numéro +17375163779, ce qui confirme que le nombre de tirages n'a pas changé.
  • La table de préfixes — 65 entrées de locale. Au moment où le défaut des doublons a été trouvé, la table contenait 959 préfixes tels qu'écrits et 957 distincts : 367 et 438 figuraient chacun deux fois dans une liste fr_CA de 11 entrées, d'où une probabilité de sélection de 18,18 % contre 9,09 % pour les sept autres codes. Recomptée le 22 juillet 2026, la table contient 963 préfixes, dont 963 distincts — les répétitions de fr_CA ont disparu de la table littérale, et la déduplication reste appliquée au moment de la sélection via array_values(array_unique(...)), par sécurité redondante.
  • La règle du chiffre initialmt_rand(1, 9) pour le premier chiffre d'abonné est appliqué aux 65 entrées. Sa justification annoncée concerne le zéro initial du format national, qui se place avant le préfixe plutôt qu'à l'intérieur de la partie abonné, si bien que la règle écarte sans raison 10 % de l'espace de génération dans les 62 locales non NANP.
  • Les chiffres d'espace de génération — calculés à partir de ng_phone_spec() comme le nombre de numéros nationaux distincts pouvant être produits par locale. Islande : 1 350 000 contre une population d'environ 390 000 habitants. Royaume-Uni : 450 000 000 contre environ 80 000 000 d'abonnements mobiles actifs, d'où l'estimation d'environ 18 % de numéros en service. Ce sont des estimations d'ordre de grandeur rapportées à des totaux d'abonnements, pas un contrôle face à une base de données d'attribution.
  • France — six racines de fiction 01 99 00 / 02 61 91 / 03 53 01 / 04 65 71 / 05 36 49 / 06 39 98, issues d'une copie extraite du plan national de numérotation de l'ARCEP, dans la table intitulée Racines (format national). Le plan cite l'annexe 2 à la décision n° 2018-0881 modifiée, qui régit la gestion du plan de numérotation en général plutôt que le bloc de fiction en particulier. Le total de 60 000 est déduit (6 × 10 000), il n'est pas énoncé dans le document.
  • Irlande089 011 0000 to 089 011 0999 is reserved for drama use, d'après une copie extraite de ComReg 15/136r4. Séparément, ComReg 15/136r1 mentionne l'indicatif 020 avec des numéros d'abonné à 7 chiffres comme Reserved for Drama purposes ; le total implicite de 10 000 000 est le nôtre, pas celui de ComReg.
  • Royaume-Uni — le bloc 07700 900000-900999 est consigné dans notre propre note d'audit comme une information déjà connue. Aucun document d'Ofcom n'est en notre possession. Un tirage de 500 000 numéros britanniques générés a produit 0 occurrence dans ce bloc, ce qui est cohérent avec le taux attendu d'environ 1 sur 450 000. La plage 01632 960xxx, fréquemment citée, n'apparaît dans aucune source que nous détenons.
  • L'audit nordique — Danemark, Suède et Norvège contrôlés face aux documents de numérotation primaires de leurs régulateurs. Aucune correction obligatoire. Le seul changement a été l'ajout des préfixes danois 24 et 25 ; la liste da_DK livrée contient désormais 26 préfixes, tous à deux chiffres, longueur nationale 8, d'où un espace de génération de 23 400 000. Vérifié directement dans ng_phone_spec() à la date ci-dessus.
  • La longueur des numéros suédoissv_SE livre 70, 72, 73, 76, 79 avec une longueur nationale fixe de 9, soit un espace de génération de 45 000 000. La table de la PTS donne maximum = minimum = 9 pour les cinq préfixes, si bien que l'affirmation fréquemment répétée selon laquelle les numéros de mobile suédois varient en longueur est fausse ; la variation appartient aux numéros géographiques suédois, qui comptent de 7 à 9 chiffres. Nos données n'ont exigé aucune modification.
  • La plage bloquée de Norvège680 50000680 59999, statut BLOKKERT, réservée par Nkom à la production de télévision et de cinéma, avec la note « Numrene i serien skal ikke brukes til ordinær bruk ». Confirmée inutilisable et sans risque de collision par inspection de la table livrée : no_NO contient 16 préfixes (40 41 45 46 47 48 90 91 92 93 94 95 96 97 98 99), dont zéro commence par 6.
  • La formulation danoise « principalement mobile » — le plan indique « Nummerserier, der er fortrinsvis afsat til mobilkommunikation ». Environ 90 sous-séries à trois chiffres situées dans des plages formellement fixes sont délivrées pour un usage mobile (342, 344349, 431, 627, 771772 parmi elles), et la portabilité est totale. Le décompte d'environ 90 provient de l'audit et n'a pas été recompté indépendamment ici. L'asymétrie entre génération et classification découle de la formulation et de la portabilité, pas d'une mesure.
  • Allemagne et Suède — les chiffres 5 210 (Bundesnetzagentur, Verfügung 148/2021) et 495 (PTS) n'ont pas pu être étayés. Aucun document de la BNetzA n'est en notre possession. Le plan de numérotation de la PTS du 8 janvier 2024 est en notre possession, mais son extraction a donné un contenu en partie binaire, sans section exploitable sur les plages réservées ; l'audit nordique ultérieur n'a pas non plus trouvé de réservation de fiction dans le plan suédois, ce qui est cohérent avec un chiffre de 495 erroné, mais ne réfute pas une réservation faite hors du plan. Les deux sont rapportés ici comme non vérifiés.
  • Japon — tables d'attribution de blocs 電気通信番号指定状況 du MIC, état au 1er septembre 2024, pour les plages 060/070/080/090. Tous les blocs 0901009099 sont attribués à des opérateurs nommés, sans aucune catégorie fiction, test, fictif ou réserve. Traité comme un résultat négatif solide, parce que les tables sont exhaustives.
  • Afrique du Sud — l'extrait du Government Gazette de l'ICASA est largement illisible et donne zéro correspondance pour « reserved », « drama », « film » et « test ». Ce n'est pas une preuve d'absence, et tout enregistrement antérieur de ce point comme résultat négatif confirmé était erroné.
  • Pays-Bas, Brésil, Inde, Islande, Finlande, Lettonie — aucun constat dans un sens ni dans l'autre. Listés comme non investigués plutôt que comme pays sans plage réservée.

← Articles