[{"data":1,"prerenderedAt":8849},["ShallowReactive",2],{"article_list_security_":3},[4,1538,4956,5755,7974,8488],{"_path":5,"_dir":6,"_draft":7,"_partial":7,"_locale":8,"title":9,"description":10,"tags":11,"image":14,"publishDate":15,"excerpt":10,"body":16,"_type":1529,"_id":1530,"_source":1531,"_file":1532,"_stem":1533,"_extension":1534,"author":1535},"/phendry/2023-01-19/badcode","2023-01-19",false,"","\"Bad\" Code (Or, Why Software Development is Hard)","Recently, the Dutch government open-sourced the iOS application for their \"DigiD\" authentication service. A tweet with a snippet of that source code, presumably making fun of it, blew up into a debate about whether mocking it is even justified. The amount of debate over such a simple snippet of code highlights, in my mind, just how tricky software development can be.",[12,13],"security","series","/phendry/2023-01-19/img/Bad Code.png","2024-01-15",{"type":17,"children":18,"toc":1524},"root",[19,47,52,734,762,797,983,988,993,1007,1012,1017,1022,1029,1034,1089,1108,1120,1125,1131,1143,1156,1161,1456,1485,1491,1496,1518],{"type":20,"tag":21,"props":22,"children":23},"element","p",{},[24,27,36,38,45],{"type":25,"value":26},"text","Recently, the Dutch government open-sourced the iOS application for their \"DigiD\" authentication service. A ",{"type":20,"tag":28,"props":29,"children":33},"a",{"href":30,"rel":31},"https://twitter.com/JeroenFrijters/status/1615204074588180481",[32],"nofollow",[34],{"type":25,"value":35},"tweet",{"type":25,"value":37}," with a snippet of that source code, presumably making fun of it, blew up into ",{"type":20,"tag":28,"props":39,"children":42},{"href":40,"rel":41},"https://old.reddit.com/r/ProgrammerHumor/comments/10dh6x1/very_efficient_code/",[32],[43],{"type":25,"value":44},"a debate",{"type":25,"value":46}," about whether mocking it is even justified. The amount of debate over such a simple snippet of code highlights, in my mind, just how tricky software development can be.",{"type":20,"tag":21,"props":48,"children":49},{},[50],{"type":25,"value":51},"Here is the code in question, written in C#:",{"type":20,"tag":53,"props":54,"children":58},"pre",{"className":55,"code":56,"language":57,"meta":8,"style":8},"language-csharp shiki shiki-themes github-light github-dark","private static string GetPercentageRounds(double percentage)\n{\n    if (percentage == 0)\n        return \"⚪⚪⚪⚪⚪⚪⚪⚪⚪⚪\";\n    if (percentage > 0.0 && percentage \u003C= 0.1)\n        return \"🔵⚪⚪⚪⚪⚪⚪⚪⚪⚪\";\n    if (percentage > 0.1 && percentage \u003C= 0.2)\n        return \"🔵🔵⚪⚪⚪⚪⚪⚪⚪⚪\";\n    if (percentage > 0.2 && percentage \u003C= 0.3)\n        return \"🔵🔵🔵⚪⚪⚪⚪⚪⚪⚪\";\n    if (percentage > 0.3 && percentage \u003C= 0.4)\n        return \"🔵🔵🔵🔵⚪⚪⚪⚪⚪⚪\";\n    if (percentage > 0.4 && percentage \u003C= 0.5)\n        return \"🔵🔵🔵🔵🔵⚪⚪⚪⚪⚪\";\n    if (percentage > 0.5 && percentage \u003C= 0.6)\n        return \"🔵🔵🔵🔵🔵🔵⚪⚪⚪⚪\";\n    if (percentage > 0.6 && percentage \u003C= 0.7)\n        return \"🔵🔵🔵🔵🔵🔵🔵⚪⚪⚪\";\n    if (percentage > 0.7 && percentage \u003C= 0.8)\n        return \"🔵🔵🔵🔵🔵🔵🔵🔵⚪⚪\";\n    if (percentage > 0.8 && percentage \u003C= 0.9)\n        return \"🔵🔵🔵🔵🔵🔵🔵🔵🔵⚪\";\n\n    return \"🔵🔵🔵🔵🔵🔵🔵🔵🔵🔵\";\n}\n","csharp",[59],{"type":20,"tag":60,"props":61,"children":62},"code",{"__ignoreMap":8},[63,112,121,150,170,216,233,274,291,332,349,390,407,448,465,506,523,564,581,622,639,680,697,707,725],{"type":20,"tag":64,"props":65,"children":68},"span",{"class":66,"line":67},"line",1,[69,75,80,85,91,97,102,107],{"type":20,"tag":64,"props":70,"children":72},{"style":71},"--shiki-default:#D73A49;--shiki-dark:#F97583",[73],{"type":25,"value":74},"private",{"type":20,"tag":64,"props":76,"children":77},{"style":71},[78],{"type":25,"value":79}," static",{"type":20,"tag":64,"props":81,"children":82},{"style":71},[83],{"type":25,"value":84}," string",{"type":20,"tag":64,"props":86,"children":88},{"style":87},"--shiki-default:#6F42C1;--shiki-dark:#B392F0",[89],{"type":25,"value":90}," GetPercentageRounds",{"type":20,"tag":64,"props":92,"children":94},{"style":93},"--shiki-default:#24292E;--shiki-dark:#E1E4E8",[95],{"type":25,"value":96},"(",{"type":20,"tag":64,"props":98,"children":99},{"style":71},[100],{"type":25,"value":101},"double",{"type":20,"tag":64,"props":103,"children":104},{"style":87},[105],{"type":25,"value":106}," percentage",{"type":20,"tag":64,"props":108,"children":109},{"style":93},[110],{"type":25,"value":111},")\n",{"type":20,"tag":64,"props":113,"children":115},{"class":66,"line":114},2,[116],{"type":20,"tag":64,"props":117,"children":118},{"style":93},[119],{"type":25,"value":120},"{\n",{"type":20,"tag":64,"props":122,"children":124},{"class":66,"line":123},3,[125,130,135,140,146],{"type":20,"tag":64,"props":126,"children":127},{"style":71},[128],{"type":25,"value":129},"    if",{"type":20,"tag":64,"props":131,"children":132},{"style":93},[133],{"type":25,"value":134}," (percentage ",{"type":20,"tag":64,"props":136,"children":137},{"style":71},[138],{"type":25,"value":139},"==",{"type":20,"tag":64,"props":141,"children":143},{"style":142},"--shiki-default:#005CC5;--shiki-dark:#79B8FF",[144],{"type":25,"value":145}," 0",{"type":20,"tag":64,"props":147,"children":148},{"style":93},[149],{"type":25,"value":111},{"type":20,"tag":64,"props":151,"children":153},{"class":66,"line":152},4,[154,159,165],{"type":20,"tag":64,"props":155,"children":156},{"style":71},[157],{"type":25,"value":158},"        return",{"type":20,"tag":64,"props":160,"children":162},{"style":161},"--shiki-default:#032F62;--shiki-dark:#9ECBFF",[163],{"type":25,"value":164}," \"⚪⚪⚪⚪⚪⚪⚪⚪⚪⚪\"",{"type":20,"tag":64,"props":166,"children":167},{"style":93},[168],{"type":25,"value":169},";\n",{"type":20,"tag":64,"props":171,"children":173},{"class":66,"line":172},5,[174,178,182,187,192,197,202,207,212],{"type":20,"tag":64,"props":175,"children":176},{"style":71},[177],{"type":25,"value":129},{"type":20,"tag":64,"props":179,"children":180},{"style":93},[181],{"type":25,"value":134},{"type":20,"tag":64,"props":183,"children":184},{"style":71},[185],{"type":25,"value":186},">",{"type":20,"tag":64,"props":188,"children":189},{"style":142},[190],{"type":25,"value":191}," 0.0",{"type":20,"tag":64,"props":193,"children":194},{"style":71},[195],{"type":25,"value":196}," &&",{"type":20,"tag":64,"props":198,"children":199},{"style":93},[200],{"type":25,"value":201}," percentage ",{"type":20,"tag":64,"props":203,"children":204},{"style":71},[205],{"type":25,"value":206},"\u003C=",{"type":20,"tag":64,"props":208,"children":209},{"style":142},[210],{"type":25,"value":211}," 0.1",{"type":20,"tag":64,"props":213,"children":214},{"style":93},[215],{"type":25,"value":111},{"type":20,"tag":64,"props":217,"children":219},{"class":66,"line":218},6,[220,224,229],{"type":20,"tag":64,"props":221,"children":222},{"style":71},[223],{"type":25,"value":158},{"type":20,"tag":64,"props":225,"children":226},{"style":161},[227],{"type":25,"value":228}," \"🔵⚪⚪⚪⚪⚪⚪⚪⚪⚪\"",{"type":20,"tag":64,"props":230,"children":231},{"style":93},[232],{"type":25,"value":169},{"type":20,"tag":64,"props":234,"children":236},{"class":66,"line":235},7,[237,241,245,249,253,257,261,265,270],{"type":20,"tag":64,"props":238,"children":239},{"style":71},[240],{"type":25,"value":129},{"type":20,"tag":64,"props":242,"children":243},{"style":93},[244],{"type":25,"value":134},{"type":20,"tag":64,"props":246,"children":247},{"style":71},[248],{"type":25,"value":186},{"type":20,"tag":64,"props":250,"children":251},{"style":142},[252],{"type":25,"value":211},{"type":20,"tag":64,"props":254,"children":255},{"style":71},[256],{"type":25,"value":196},{"type":20,"tag":64,"props":258,"children":259},{"style":93},[260],{"type":25,"value":201},{"type":20,"tag":64,"props":262,"children":263},{"style":71},[264],{"type":25,"value":206},{"type":20,"tag":64,"props":266,"children":267},{"style":142},[268],{"type":25,"value":269}," 0.2",{"type":20,"tag":64,"props":271,"children":272},{"style":93},[273],{"type":25,"value":111},{"type":20,"tag":64,"props":275,"children":277},{"class":66,"line":276},8,[278,282,287],{"type":20,"tag":64,"props":279,"children":280},{"style":71},[281],{"type":25,"value":158},{"type":20,"tag":64,"props":283,"children":284},{"style":161},[285],{"type":25,"value":286}," \"🔵🔵⚪⚪⚪⚪⚪⚪⚪⚪\"",{"type":20,"tag":64,"props":288,"children":289},{"style":93},[290],{"type":25,"value":169},{"type":20,"tag":64,"props":292,"children":294},{"class":66,"line":293},9,[295,299,303,307,311,315,319,323,328],{"type":20,"tag":64,"props":296,"children":297},{"style":71},[298],{"type":25,"value":129},{"type":20,"tag":64,"props":300,"children":301},{"style":93},[302],{"type":25,"value":134},{"type":20,"tag":64,"props":304,"children":305},{"style":71},[306],{"type":25,"value":186},{"type":20,"tag":64,"props":308,"children":309},{"style":142},[310],{"type":25,"value":269},{"type":20,"tag":64,"props":312,"children":313},{"style":71},[314],{"type":25,"value":196},{"type":20,"tag":64,"props":316,"children":317},{"style":93},[318],{"type":25,"value":201},{"type":20,"tag":64,"props":320,"children":321},{"style":71},[322],{"type":25,"value":206},{"type":20,"tag":64,"props":324,"children":325},{"style":142},[326],{"type":25,"value":327}," 0.3",{"type":20,"tag":64,"props":329,"children":330},{"style":93},[331],{"type":25,"value":111},{"type":20,"tag":64,"props":333,"children":335},{"class":66,"line":334},10,[336,340,345],{"type":20,"tag":64,"props":337,"children":338},{"style":71},[339],{"type":25,"value":158},{"type":20,"tag":64,"props":341,"children":342},{"style":161},[343],{"type":25,"value":344}," \"🔵🔵🔵⚪⚪⚪⚪⚪⚪⚪\"",{"type":20,"tag":64,"props":346,"children":347},{"style":93},[348],{"type":25,"value":169},{"type":20,"tag":64,"props":350,"children":352},{"class":66,"line":351},11,[353,357,361,365,369,373,377,381,386],{"type":20,"tag":64,"props":354,"children":355},{"style":71},[356],{"type":25,"value":129},{"type":20,"tag":64,"props":358,"children":359},{"style":93},[360],{"type":25,"value":134},{"type":20,"tag":64,"props":362,"children":363},{"style":71},[364],{"type":25,"value":186},{"type":20,"tag":64,"props":366,"children":367},{"style":142},[368],{"type":25,"value":327},{"type":20,"tag":64,"props":370,"children":371},{"style":71},[372],{"type":25,"value":196},{"type":20,"tag":64,"props":374,"children":375},{"style":93},[376],{"type":25,"value":201},{"type":20,"tag":64,"props":378,"children":379},{"style":71},[380],{"type":25,"value":206},{"type":20,"tag":64,"props":382,"children":383},{"style":142},[384],{"type":25,"value":385}," 0.4",{"type":20,"tag":64,"props":387,"children":388},{"style":93},[389],{"type":25,"value":111},{"type":20,"tag":64,"props":391,"children":393},{"class":66,"line":392},12,[394,398,403],{"type":20,"tag":64,"props":395,"children":396},{"style":71},[397],{"type":25,"value":158},{"type":20,"tag":64,"props":399,"children":400},{"style":161},[401],{"type":25,"value":402}," \"🔵🔵🔵🔵⚪⚪⚪⚪⚪⚪\"",{"type":20,"tag":64,"props":404,"children":405},{"style":93},[406],{"type":25,"value":169},{"type":20,"tag":64,"props":408,"children":410},{"class":66,"line":409},13,[411,415,419,423,427,431,435,439,444],{"type":20,"tag":64,"props":412,"children":413},{"style":71},[414],{"type":25,"value":129},{"type":20,"tag":64,"props":416,"children":417},{"style":93},[418],{"type":25,"value":134},{"type":20,"tag":64,"props":420,"children":421},{"style":71},[422],{"type":25,"value":186},{"type":20,"tag":64,"props":424,"children":425},{"style":142},[426],{"type":25,"value":385},{"type":20,"tag":64,"props":428,"children":429},{"style":71},[430],{"type":25,"value":196},{"type":20,"tag":64,"props":432,"children":433},{"style":93},[434],{"type":25,"value":201},{"type":20,"tag":64,"props":436,"children":437},{"style":71},[438],{"type":25,"value":206},{"type":20,"tag":64,"props":440,"children":441},{"style":142},[442],{"type":25,"value":443}," 0.5",{"type":20,"tag":64,"props":445,"children":446},{"style":93},[447],{"type":25,"value":111},{"type":20,"tag":64,"props":449,"children":451},{"class":66,"line":450},14,[452,456,461],{"type":20,"tag":64,"props":453,"children":454},{"style":71},[455],{"type":25,"value":158},{"type":20,"tag":64,"props":457,"children":458},{"style":161},[459],{"type":25,"value":460}," \"🔵🔵🔵🔵🔵⚪⚪⚪⚪⚪\"",{"type":20,"tag":64,"props":462,"children":463},{"style":93},[464],{"type":25,"value":169},{"type":20,"tag":64,"props":466,"children":468},{"class":66,"line":467},15,[469,473,477,481,485,489,493,497,502],{"type":20,"tag":64,"props":470,"children":471},{"style":71},[472],{"type":25,"value":129},{"type":20,"tag":64,"props":474,"children":475},{"style":93},[476],{"type":25,"value":134},{"type":20,"tag":64,"props":478,"children":479},{"style":71},[480],{"type":25,"value":186},{"type":20,"tag":64,"props":482,"children":483},{"style":142},[484],{"type":25,"value":443},{"type":20,"tag":64,"props":486,"children":487},{"style":71},[488],{"type":25,"value":196},{"type":20,"tag":64,"props":490,"children":491},{"style":93},[492],{"type":25,"value":201},{"type":20,"tag":64,"props":494,"children":495},{"style":71},[496],{"type":25,"value":206},{"type":20,"tag":64,"props":498,"children":499},{"style":142},[500],{"type":25,"value":501}," 0.6",{"type":20,"tag":64,"props":503,"children":504},{"style":93},[505],{"type":25,"value":111},{"type":20,"tag":64,"props":507,"children":509},{"class":66,"line":508},16,[510,514,519],{"type":20,"tag":64,"props":511,"children":512},{"style":71},[513],{"type":25,"value":158},{"type":20,"tag":64,"props":515,"children":516},{"style":161},[517],{"type":25,"value":518}," \"🔵🔵🔵🔵🔵🔵⚪⚪⚪⚪\"",{"type":20,"tag":64,"props":520,"children":521},{"style":93},[522],{"type":25,"value":169},{"type":20,"tag":64,"props":524,"children":526},{"class":66,"line":525},17,[527,531,535,539,543,547,551,555,560],{"type":20,"tag":64,"props":528,"children":529},{"style":71},[530],{"type":25,"value":129},{"type":20,"tag":64,"props":532,"children":533},{"style":93},[534],{"type":25,"value":134},{"type":20,"tag":64,"props":536,"children":537},{"style":71},[538],{"type":25,"value":186},{"type":20,"tag":64,"props":540,"children":541},{"style":142},[542],{"type":25,"value":501},{"type":20,"tag":64,"props":544,"children":545},{"style":71},[546],{"type":25,"value":196},{"type":20,"tag":64,"props":548,"children":549},{"style":93},[550],{"type":25,"value":201},{"type":20,"tag":64,"props":552,"children":553},{"style":71},[554],{"type":25,"value":206},{"type":20,"tag":64,"props":556,"children":557},{"style":142},[558],{"type":25,"value":559}," 0.7",{"type":20,"tag":64,"props":561,"children":562},{"style":93},[563],{"type":25,"value":111},{"type":20,"tag":64,"props":565,"children":567},{"class":66,"line":566},18,[568,572,577],{"type":20,"tag":64,"props":569,"children":570},{"style":71},[571],{"type":25,"value":158},{"type":20,"tag":64,"props":573,"children":574},{"style":161},[575],{"type":25,"value":576}," \"🔵🔵🔵🔵🔵🔵🔵⚪⚪⚪\"",{"type":20,"tag":64,"props":578,"children":579},{"style":93},[580],{"type":25,"value":169},{"type":20,"tag":64,"props":582,"children":584},{"class":66,"line":583},19,[585,589,593,597,601,605,609,613,618],{"type":20,"tag":64,"props":586,"children":587},{"style":71},[588],{"type":25,"value":129},{"type":20,"tag":64,"props":590,"children":591},{"style":93},[592],{"type":25,"value":134},{"type":20,"tag":64,"props":594,"children":595},{"style":71},[596],{"type":25,"value":186},{"type":20,"tag":64,"props":598,"children":599},{"style":142},[600],{"type":25,"value":559},{"type":20,"tag":64,"props":602,"children":603},{"style":71},[604],{"type":25,"value":196},{"type":20,"tag":64,"props":606,"children":607},{"style":93},[608],{"type":25,"value":201},{"type":20,"tag":64,"props":610,"children":611},{"style":71},[612],{"type":25,"value":206},{"type":20,"tag":64,"props":614,"children":615},{"style":142},[616],{"type":25,"value":617}," 0.8",{"type":20,"tag":64,"props":619,"children":620},{"style":93},[621],{"type":25,"value":111},{"type":20,"tag":64,"props":623,"children":625},{"class":66,"line":624},20,[626,630,635],{"type":20,"tag":64,"props":627,"children":628},{"style":71},[629],{"type":25,"value":158},{"type":20,"tag":64,"props":631,"children":632},{"style":161},[633],{"type":25,"value":634}," \"🔵🔵🔵🔵🔵🔵🔵🔵⚪⚪\"",{"type":20,"tag":64,"props":636,"children":637},{"style":93},[638],{"type":25,"value":169},{"type":20,"tag":64,"props":640,"children":642},{"class":66,"line":641},21,[643,647,651,655,659,663,667,671,676],{"type":20,"tag":64,"props":644,"children":645},{"style":71},[646],{"type":25,"value":129},{"type":20,"tag":64,"props":648,"children":649},{"style":93},[650],{"type":25,"value":134},{"type":20,"tag":64,"props":652,"children":653},{"style":71},[654],{"type":25,"value":186},{"type":20,"tag":64,"props":656,"children":657},{"style":142},[658],{"type":25,"value":617},{"type":20,"tag":64,"props":660,"children":661},{"style":71},[662],{"type":25,"value":196},{"type":20,"tag":64,"props":664,"children":665},{"style":93},[666],{"type":25,"value":201},{"type":20,"tag":64,"props":668,"children":669},{"style":71},[670],{"type":25,"value":206},{"type":20,"tag":64,"props":672,"children":673},{"style":142},[674],{"type":25,"value":675}," 0.9",{"type":20,"tag":64,"props":677,"children":678},{"style":93},[679],{"type":25,"value":111},{"type":20,"tag":64,"props":681,"children":683},{"class":66,"line":682},22,[684,688,693],{"type":20,"tag":64,"props":685,"children":686},{"style":71},[687],{"type":25,"value":158},{"type":20,"tag":64,"props":689,"children":690},{"style":161},[691],{"type":25,"value":692}," \"🔵🔵🔵🔵🔵🔵🔵🔵🔵⚪\"",{"type":20,"tag":64,"props":694,"children":695},{"style":93},[696],{"type":25,"value":169},{"type":20,"tag":64,"props":698,"children":700},{"class":66,"line":699},23,[701],{"type":20,"tag":64,"props":702,"children":704},{"emptyLinePlaceholder":703},true,[705],{"type":25,"value":706},"\n",{"type":20,"tag":64,"props":708,"children":710},{"class":66,"line":709},24,[711,716,721],{"type":20,"tag":64,"props":712,"children":713},{"style":71},[714],{"type":25,"value":715},"    return",{"type":20,"tag":64,"props":717,"children":718},{"style":161},[719],{"type":25,"value":720}," \"🔵🔵🔵🔵🔵🔵🔵🔵🔵🔵\"",{"type":20,"tag":64,"props":722,"children":723},{"style":93},[724],{"type":25,"value":169},{"type":20,"tag":64,"props":726,"children":728},{"class":66,"line":727},25,[729],{"type":20,"tag":64,"props":730,"children":731},{"style":93},[732],{"type":25,"value":733},"}\n",{"type":20,"tag":21,"props":735,"children":736},{},[737,739,745,747,753,755,760],{"type":25,"value":738},"Let's ignore the lack of parameter validation (namely of ensuring that ",{"type":20,"tag":60,"props":740,"children":742},{"className":741},[],[743],{"type":25,"value":744},"percentage",{"type":25,"value":746}," is not ",{"type":20,"tag":60,"props":748,"children":750},{"className":749},[],[751],{"type":25,"value":752},"NaN",{"type":25,"value":754},", negative, or infinity), since it would be the same regardless of solution, and it's not uncommon to omit that sort of rigorous error handling in a ",{"type":20,"tag":60,"props":756,"children":758},{"className":757},[],[759],{"type":25,"value":74},{"type":25,"value":761}," method.",{"type":20,"tag":21,"props":763,"children":764},{},[765,767,773,775,781,783,788,790,795],{"type":25,"value":766},"Aside from that, well... it omits curly brackets in the ",{"type":20,"tag":60,"props":768,"children":770},{"className":769},[],[771],{"type":25,"value":772},"if",{"type":25,"value":774}," blocks, which is a style thing many people dislike. It's ",{"type":20,"tag":776,"props":777,"children":778},"em",{},[779],{"type":25,"value":780},"very",{"type":25,"value":782}," repetitious. It has unnecessary greater-than conditions (since each prior ",{"type":20,"tag":60,"props":784,"children":786},{"className":785},[],[787],{"type":25,"value":772},{"type":25,"value":789},"'s less-than-equal condition guarantees it). It does several more ",{"type":20,"tag":60,"props":791,"children":793},{"className":792},[],[794],{"type":25,"value":772},{"type":25,"value":796}," comparisons than it technically needs to. In fact, given that the output is linearly related to the input, this can be a one-liner with just a little bit of math; let's call it the \"math solution\".",{"type":20,"tag":53,"props":798,"children":800},{"className":55,"code":799,"language":57,"meta":8,"style":8},"private static string GetPercentageRounds(double percentage)\n{\n    int stage = (int)Math.Ceiling(percentage * 10);\n    return new string('🔵', stage) + new string('⚪', 10 - stage);\n}\n",[801],{"type":20,"tag":60,"props":802,"children":803},{"__ignoreMap":8},[804,839,846,904,976],{"type":20,"tag":64,"props":805,"children":806},{"class":66,"line":67},[807,811,815,819,823,827,831,835],{"type":20,"tag":64,"props":808,"children":809},{"style":71},[810],{"type":25,"value":74},{"type":20,"tag":64,"props":812,"children":813},{"style":71},[814],{"type":25,"value":79},{"type":20,"tag":64,"props":816,"children":817},{"style":71},[818],{"type":25,"value":84},{"type":20,"tag":64,"props":820,"children":821},{"style":87},[822],{"type":25,"value":90},{"type":20,"tag":64,"props":824,"children":825},{"style":93},[826],{"type":25,"value":96},{"type":20,"tag":64,"props":828,"children":829},{"style":71},[830],{"type":25,"value":101},{"type":20,"tag":64,"props":832,"children":833},{"style":87},[834],{"type":25,"value":106},{"type":20,"tag":64,"props":836,"children":837},{"style":93},[838],{"type":25,"value":111},{"type":20,"tag":64,"props":840,"children":841},{"class":66,"line":114},[842],{"type":20,"tag":64,"props":843,"children":844},{"style":93},[845],{"type":25,"value":120},{"type":20,"tag":64,"props":847,"children":848},{"class":66,"line":123},[849,854,859,864,869,874,879,884,889,894,899],{"type":20,"tag":64,"props":850,"children":851},{"style":71},[852],{"type":25,"value":853},"    int",{"type":20,"tag":64,"props":855,"children":856},{"style":87},[857],{"type":25,"value":858}," stage",{"type":20,"tag":64,"props":860,"children":861},{"style":71},[862],{"type":25,"value":863}," =",{"type":20,"tag":64,"props":865,"children":866},{"style":93},[867],{"type":25,"value":868}," (",{"type":20,"tag":64,"props":870,"children":871},{"style":71},[872],{"type":25,"value":873},"int",{"type":20,"tag":64,"props":875,"children":876},{"style":93},[877],{"type":25,"value":878},")Math.",{"type":20,"tag":64,"props":880,"children":881},{"style":87},[882],{"type":25,"value":883},"Ceiling",{"type":20,"tag":64,"props":885,"children":886},{"style":93},[887],{"type":25,"value":888},"(percentage ",{"type":20,"tag":64,"props":890,"children":891},{"style":71},[892],{"type":25,"value":893},"*",{"type":20,"tag":64,"props":895,"children":896},{"style":142},[897],{"type":25,"value":898}," 10",{"type":20,"tag":64,"props":900,"children":901},{"style":93},[902],{"type":25,"value":903},");\n",{"type":20,"tag":64,"props":905,"children":906},{"class":66,"line":152},[907,911,916,920,924,929,934,939,943,947,951,956,961,966,971],{"type":20,"tag":64,"props":908,"children":909},{"style":71},[910],{"type":25,"value":715},{"type":20,"tag":64,"props":912,"children":913},{"style":71},[914],{"type":25,"value":915}," new",{"type":20,"tag":64,"props":917,"children":918},{"style":71},[919],{"type":25,"value":84},{"type":20,"tag":64,"props":921,"children":922},{"style":93},[923],{"type":25,"value":96},{"type":20,"tag":64,"props":925,"children":926},{"style":161},[927],{"type":25,"value":928},"'🔵'",{"type":20,"tag":64,"props":930,"children":931},{"style":93},[932],{"type":25,"value":933},", stage) ",{"type":20,"tag":64,"props":935,"children":936},{"style":71},[937],{"type":25,"value":938},"+",{"type":20,"tag":64,"props":940,"children":941},{"style":71},[942],{"type":25,"value":915},{"type":20,"tag":64,"props":944,"children":945},{"style":71},[946],{"type":25,"value":84},{"type":20,"tag":64,"props":948,"children":949},{"style":93},[950],{"type":25,"value":96},{"type":20,"tag":64,"props":952,"children":953},{"style":161},[954],{"type":25,"value":955},"'⚪'",{"type":20,"tag":64,"props":957,"children":958},{"style":93},[959],{"type":25,"value":960},", ",{"type":20,"tag":64,"props":962,"children":963},{"style":142},[964],{"type":25,"value":965},"10",{"type":20,"tag":64,"props":967,"children":968},{"style":71},[969],{"type":25,"value":970}," -",{"type":20,"tag":64,"props":972,"children":973},{"style":93},[974],{"type":25,"value":975}," stage);\n",{"type":20,"tag":64,"props":977,"children":978},{"class":66,"line":172},[979],{"type":20,"tag":64,"props":980,"children":981},{"style":93},[982],{"type":25,"value":733},{"type":20,"tag":21,"props":984,"children":985},{},[986],{"type":25,"value":987},"Repetition avoided; 21 lines reduced to 2. Problem solved...",{"type":20,"tag":21,"props":989,"children":990},{},[991],{"type":25,"value":992},"...although if I were come back to that code in a month's time, I'd definitely have to stare at it longer to figure out what it does...",{"type":20,"tag":21,"props":994,"children":995},{},[996,998,1005],{"type":25,"value":997},"...and I'm not 100% confident that the multiplication won't cause ",{"type":20,"tag":28,"props":999,"children":1002},{"href":1000,"rel":1001},"https://floating-point-gui.de/errors/comparison/",[32],[1003],{"type":25,"value":1004},"floating point edge cases",{"type":25,"value":1006},"...",{"type":20,"tag":21,"props":1008,"children":1009},{},[1010],{"type":25,"value":1011},"...and I guess it's less flexible now (e.g. to adjust the color of individual dots by stage)...",{"type":20,"tag":21,"props":1013,"children":1014},{},[1015],{"type":25,"value":1016},"...and it's doing three string allocations now instead of returning a constant, so maybe that has performance implications...",{"type":20,"tag":21,"props":1018,"children":1019},{},[1020],{"type":25,"value":1021},"...hmm. Maybe we need to remind ourselves of what \"good\" code is.",{"type":20,"tag":1023,"props":1024,"children":1026},"h2",{"id":1025},"question-what-is-good-code-answer-code-that-makes-the-right-tradeoffs",[1027],{"type":25,"value":1028},"Question: What is Good Code? Answer: Code That Makes The Right Tradeoffs.",{"type":20,"tag":21,"props":1030,"children":1031},{},[1032],{"type":25,"value":1033},"Good code has a number of qualities most developers would agree on:",{"type":20,"tag":1035,"props":1036,"children":1037},"ol",{},[1038,1052,1069,1079],{"type":20,"tag":1039,"props":1040,"children":1041},"li",{},[1042,1044,1050],{"type":25,"value":1043},"Arguably the most important, ",{"type":20,"tag":1045,"props":1046,"children":1047},"strong",{},[1048],{"type":25,"value":1049},"good code is readable",{"type":25,"value":1051},". Code is written once but it is read many times, and understanding code is key to maintaining and extending it, so a solution that is easy to read and understand is usually better than one that is more clever.",{"type":20,"tag":1039,"props":1053,"children":1054},{},[1055,1060,1062,1067],{"type":20,"tag":1045,"props":1056,"children":1057},{},[1058],{"type":25,"value":1059},"Good code is correct",{"type":25,"value":1061},"; it does what it's supposed to do. OK, ",{"type":20,"tag":776,"props":1063,"children":1064},{},[1065],{"type":25,"value":1066},"maybe",{"type":25,"value":1068}," this is more important than readability, but then again, it's easy to fix a bug in readable code.",{"type":20,"tag":1039,"props":1070,"children":1071},{},[1072,1077],{"type":20,"tag":1045,"props":1073,"children":1074},{},[1075],{"type":25,"value":1076},"Good code is performant",{"type":25,"value":1078},"; it should not needlessly waste system resources.",{"type":20,"tag":1039,"props":1080,"children":1081},{},[1082,1087],{"type":20,"tag":1045,"props":1083,"children":1084},{},[1085],{"type":25,"value":1086},"Good code is easy to write",{"type":25,"value":1088},", since productivity is important.",{"type":20,"tag":21,"props":1090,"children":1091},{},[1092,1094,1099,1101,1106],{"type":25,"value":1093},"Often, even ",{"type":20,"tag":776,"props":1095,"children":1096},{},[1097],{"type":25,"value":1098},"usually",{"type":25,"value":1100},", some of these qualities are at odds with one another. Making code more readable often means not choosing the most performant possible solution, and similarly, optimizing a solution often makes it less readable. Code that's easy to write is often not readable, performant ",{"type":20,"tag":776,"props":1102,"children":1103},{},[1104],{"type":25,"value":1105},"or",{"type":25,"value":1107}," correct.",{"type":20,"tag":21,"props":1109,"children":1110},{},[1111,1113,1118],{"type":25,"value":1112},"What this means is that what makes for \"good\" code always depends on the circumstances of that code: its purpose, the code surrounding it, the current and future priorities of the end client or product manager, etc. We don't even ",{"type":20,"tag":776,"props":1114,"children":1115},{},[1116],{"type":25,"value":1117},"know",{"type":25,"value":1119}," all those circumstances at the time the code is written, so we're doomed to never truly know what the best solution is, and just come up with the best we can.",{"type":20,"tag":21,"props":1121,"children":1122},{},[1123],{"type":25,"value":1124},"With that in mind, let's have another go at comparing the qualities of these two solutions, along with yet another one added to the mix.",{"type":20,"tag":1023,"props":1126,"children":1128},{"id":1127},"comparing-solutions",[1129],{"type":25,"value":1130},"Comparing Solutions",{"type":20,"tag":21,"props":1132,"children":1133},{},[1134,1136,1141],{"type":25,"value":1135},"The \"original\" solution is understandable at a glance, it doesn't use any fancy features a junior developer might not understand, it doesn't do any dynamic string allocations, and it's flexible for a few types of future changes (e.g. changing dot colors per stage or per position). On the other hand, it's many lines of code, it's repetitious, and its many ",{"type":20,"tag":60,"props":1137,"children":1139},{"className":1138},[],[1140],{"type":25,"value":772},{"type":25,"value":1142}," comparisons could be a performance problem if called in a tight loop.",{"type":20,"tag":21,"props":1144,"children":1145},{},[1146,1148,1154],{"type":25,"value":1147},"The \"math\" solution is about as compact as a solution could be, and consequently it's quite elegant too. On the other hand, that makes it harder to read, it's not as flexible for potential future changes, and its multiple ",{"type":20,"tag":60,"props":1149,"children":1151},{"className":1150},[],[1152],{"type":25,"value":1153},"string",{"type":25,"value":1155}," allocations could be its own sort of performance problem.",{"type":20,"tag":21,"props":1157,"children":1158},{},[1159],{"type":25,"value":1160},"The third one is a blend that we can call the \"array\" solution:",{"type":20,"tag":53,"props":1162,"children":1164},{"className":55,"code":1163,"language":57,"meta":8,"style":8},"private static readonly string[] Rounds = {\n    \"⚪⚪⚪⚪⚪⚪⚪⚪⚪⚪\",\n    \"🔵⚪⚪⚪⚪⚪⚪⚪⚪⚪\",\n    \"🔵🔵⚪⚪⚪⚪⚪⚪⚪⚪\",\n    \"🔵🔵🔵⚪⚪⚪⚪⚪⚪⚪\",\n    \"🔵🔵🔵🔵⚪⚪⚪⚪⚪⚪\",\n    \"🔵🔵🔵🔵🔵⚪⚪⚪⚪⚪\",\n    \"🔵🔵🔵🔵🔵🔵⚪⚪⚪⚪\",\n    \"🔵🔵🔵🔵🔵🔵🔵⚪⚪⚪\",\n    \"🔵🔵🔵🔵🔵🔵🔵🔵⚪⚪\",\n    \"🔵🔵🔵🔵🔵🔵🔵🔵🔵⚪\",\n    \"🔵🔵🔵🔵🔵🔵🔵🔵🔵🔵\",\n};\n\nprivate static string GetPercentageRounds(double percentage)\n{\n    return Rounds[(int)Math.Ceiling(percentage * (Rounds.Length - 1))];\n}\n",[1165],{"type":20,"tag":60,"props":1166,"children":1167},{"__ignoreMap":8},[1168,1207,1220,1232,1244,1256,1268,1280,1292,1304,1316,1328,1340,1348,1355,1390,1397,1449],{"type":20,"tag":64,"props":1169,"children":1170},{"class":66,"line":67},[1171,1175,1179,1184,1188,1193,1198,1202],{"type":20,"tag":64,"props":1172,"children":1173},{"style":71},[1174],{"type":25,"value":74},{"type":20,"tag":64,"props":1176,"children":1177},{"style":71},[1178],{"type":25,"value":79},{"type":20,"tag":64,"props":1180,"children":1181},{"style":71},[1182],{"type":25,"value":1183}," readonly",{"type":20,"tag":64,"props":1185,"children":1186},{"style":71},[1187],{"type":25,"value":84},{"type":20,"tag":64,"props":1189,"children":1190},{"style":93},[1191],{"type":25,"value":1192},"[] ",{"type":20,"tag":64,"props":1194,"children":1195},{"style":87},[1196],{"type":25,"value":1197},"Rounds",{"type":20,"tag":64,"props":1199,"children":1200},{"style":71},[1201],{"type":25,"value":863},{"type":20,"tag":64,"props":1203,"children":1204},{"style":93},[1205],{"type":25,"value":1206}," {\n",{"type":20,"tag":64,"props":1208,"children":1209},{"class":66,"line":114},[1210,1215],{"type":20,"tag":64,"props":1211,"children":1212},{"style":161},[1213],{"type":25,"value":1214},"    \"⚪⚪⚪⚪⚪⚪⚪⚪⚪⚪\"",{"type":20,"tag":64,"props":1216,"children":1217},{"style":93},[1218],{"type":25,"value":1219},",\n",{"type":20,"tag":64,"props":1221,"children":1222},{"class":66,"line":123},[1223,1228],{"type":20,"tag":64,"props":1224,"children":1225},{"style":161},[1226],{"type":25,"value":1227},"    \"🔵⚪⚪⚪⚪⚪⚪⚪⚪⚪\"",{"type":20,"tag":64,"props":1229,"children":1230},{"style":93},[1231],{"type":25,"value":1219},{"type":20,"tag":64,"props":1233,"children":1234},{"class":66,"line":152},[1235,1240],{"type":20,"tag":64,"props":1236,"children":1237},{"style":161},[1238],{"type":25,"value":1239},"    \"🔵🔵⚪⚪⚪⚪⚪⚪⚪⚪\"",{"type":20,"tag":64,"props":1241,"children":1242},{"style":93},[1243],{"type":25,"value":1219},{"type":20,"tag":64,"props":1245,"children":1246},{"class":66,"line":172},[1247,1252],{"type":20,"tag":64,"props":1248,"children":1249},{"style":161},[1250],{"type":25,"value":1251},"    \"🔵🔵🔵⚪⚪⚪⚪⚪⚪⚪\"",{"type":20,"tag":64,"props":1253,"children":1254},{"style":93},[1255],{"type":25,"value":1219},{"type":20,"tag":64,"props":1257,"children":1258},{"class":66,"line":218},[1259,1264],{"type":20,"tag":64,"props":1260,"children":1261},{"style":161},[1262],{"type":25,"value":1263},"    \"🔵🔵🔵🔵⚪⚪⚪⚪⚪⚪\"",{"type":20,"tag":64,"props":1265,"children":1266},{"style":93},[1267],{"type":25,"value":1219},{"type":20,"tag":64,"props":1269,"children":1270},{"class":66,"line":235},[1271,1276],{"type":20,"tag":64,"props":1272,"children":1273},{"style":161},[1274],{"type":25,"value":1275},"    \"🔵🔵🔵🔵🔵⚪⚪⚪⚪⚪\"",{"type":20,"tag":64,"props":1277,"children":1278},{"style":93},[1279],{"type":25,"value":1219},{"type":20,"tag":64,"props":1281,"children":1282},{"class":66,"line":276},[1283,1288],{"type":20,"tag":64,"props":1284,"children":1285},{"style":161},[1286],{"type":25,"value":1287},"    \"🔵🔵🔵🔵🔵🔵⚪⚪⚪⚪\"",{"type":20,"tag":64,"props":1289,"children":1290},{"style":93},[1291],{"type":25,"value":1219},{"type":20,"tag":64,"props":1293,"children":1294},{"class":66,"line":293},[1295,1300],{"type":20,"tag":64,"props":1296,"children":1297},{"style":161},[1298],{"type":25,"value":1299},"    \"🔵🔵🔵🔵🔵🔵🔵⚪⚪⚪\"",{"type":20,"tag":64,"props":1301,"children":1302},{"style":93},[1303],{"type":25,"value":1219},{"type":20,"tag":64,"props":1305,"children":1306},{"class":66,"line":334},[1307,1312],{"type":20,"tag":64,"props":1308,"children":1309},{"style":161},[1310],{"type":25,"value":1311},"    \"🔵🔵🔵🔵🔵🔵🔵🔵⚪⚪\"",{"type":20,"tag":64,"props":1313,"children":1314},{"style":93},[1315],{"type":25,"value":1219},{"type":20,"tag":64,"props":1317,"children":1318},{"class":66,"line":351},[1319,1324],{"type":20,"tag":64,"props":1320,"children":1321},{"style":161},[1322],{"type":25,"value":1323},"    \"🔵🔵🔵🔵🔵🔵🔵🔵🔵⚪\"",{"type":20,"tag":64,"props":1325,"children":1326},{"style":93},[1327],{"type":25,"value":1219},{"type":20,"tag":64,"props":1329,"children":1330},{"class":66,"line":392},[1331,1336],{"type":20,"tag":64,"props":1332,"children":1333},{"style":161},[1334],{"type":25,"value":1335},"    \"🔵🔵🔵🔵🔵🔵🔵🔵🔵🔵\"",{"type":20,"tag":64,"props":1337,"children":1338},{"style":93},[1339],{"type":25,"value":1219},{"type":20,"tag":64,"props":1341,"children":1342},{"class":66,"line":409},[1343],{"type":20,"tag":64,"props":1344,"children":1345},{"style":93},[1346],{"type":25,"value":1347},"};\n",{"type":20,"tag":64,"props":1349,"children":1350},{"class":66,"line":450},[1351],{"type":20,"tag":64,"props":1352,"children":1353},{"emptyLinePlaceholder":703},[1354],{"type":25,"value":706},{"type":20,"tag":64,"props":1356,"children":1357},{"class":66,"line":467},[1358,1362,1366,1370,1374,1378,1382,1386],{"type":20,"tag":64,"props":1359,"children":1360},{"style":71},[1361],{"type":25,"value":74},{"type":20,"tag":64,"props":1363,"children":1364},{"style":71},[1365],{"type":25,"value":79},{"type":20,"tag":64,"props":1367,"children":1368},{"style":71},[1369],{"type":25,"value":84},{"type":20,"tag":64,"props":1371,"children":1372},{"style":87},[1373],{"type":25,"value":90},{"type":20,"tag":64,"props":1375,"children":1376},{"style":93},[1377],{"type":25,"value":96},{"type":20,"tag":64,"props":1379,"children":1380},{"style":71},[1381],{"type":25,"value":101},{"type":20,"tag":64,"props":1383,"children":1384},{"style":87},[1385],{"type":25,"value":106},{"type":20,"tag":64,"props":1387,"children":1388},{"style":93},[1389],{"type":25,"value":111},{"type":20,"tag":64,"props":1391,"children":1392},{"class":66,"line":508},[1393],{"type":20,"tag":64,"props":1394,"children":1395},{"style":93},[1396],{"type":25,"value":120},{"type":20,"tag":64,"props":1398,"children":1399},{"class":66,"line":525},[1400,1404,1409,1413,1417,1421,1425,1429,1434,1439,1444],{"type":20,"tag":64,"props":1401,"children":1402},{"style":71},[1403],{"type":25,"value":715},{"type":20,"tag":64,"props":1405,"children":1406},{"style":93},[1407],{"type":25,"value":1408}," Rounds[(",{"type":20,"tag":64,"props":1410,"children":1411},{"style":71},[1412],{"type":25,"value":873},{"type":20,"tag":64,"props":1414,"children":1415},{"style":93},[1416],{"type":25,"value":878},{"type":20,"tag":64,"props":1418,"children":1419},{"style":87},[1420],{"type":25,"value":883},{"type":20,"tag":64,"props":1422,"children":1423},{"style":93},[1424],{"type":25,"value":888},{"type":20,"tag":64,"props":1426,"children":1427},{"style":71},[1428],{"type":25,"value":893},{"type":20,"tag":64,"props":1430,"children":1431},{"style":93},[1432],{"type":25,"value":1433}," (Rounds.Length ",{"type":20,"tag":64,"props":1435,"children":1436},{"style":71},[1437],{"type":25,"value":1438},"-",{"type":20,"tag":64,"props":1440,"children":1441},{"style":142},[1442],{"type":25,"value":1443}," 1",{"type":20,"tag":64,"props":1445,"children":1446},{"style":93},[1447],{"type":25,"value":1448},"))];\n",{"type":20,"tag":64,"props":1450,"children":1451},{"class":66,"line":566},[1452],{"type":20,"tag":64,"props":1453,"children":1454},{"style":93},[1455],{"type":25,"value":733},{"type":20,"tag":21,"props":1457,"children":1458},{},[1459,1461,1466,1468,1474,1476,1483],{"type":25,"value":1460},"This one has the same at-a-glance readability of the original solution, it's even more flexible since it works with an arbitrary number of loading stages, and it makes no dynamic ",{"type":20,"tag":60,"props":1462,"children":1464},{"className":1463},[],[1465],{"type":25,"value":1153},{"type":25,"value":1467}," allocations. On the other hand, it requires a separate ",{"type":20,"tag":60,"props":1469,"children":1471},{"className":1470},[],[1472],{"type":25,"value":1473},"static readonly string[]",{"type":25,"value":1475}," that's external to the method (hampering readability), and its main advantage over the simpler original or \"math\" solutions is just performance, something which is likely a ",{"type":20,"tag":28,"props":1477,"children":1480},{"href":1478,"rel":1479},"https://wiki.c2.com/?PrematureOptimization",[32],[1481],{"type":25,"value":1482},"premature optimization",{"type":25,"value":1484}," for a method like this (particularly since we haven't actually measured to confirm that it is faster).",{"type":20,"tag":1023,"props":1486,"children":1488},{"id":1487},"so-which-solution-is-best",[1489],{"type":25,"value":1490},"So, Which Solution Is Best?",{"type":20,"tag":21,"props":1492,"children":1493},{},[1494],{"type":25,"value":1495},"None of them and all of them, I would argue. A developer might have their own preference, but none of the solutions are truly so bad that they ought to be condemned in a code review.",{"type":20,"tag":21,"props":1497,"children":1498},{},[1499,1501,1508,1510,1516],{"type":25,"value":1500},"The debate over this snippet of code reminds me how hard software development can be: here's a piece of code which is trivial enough that debating it is almost certainly ",{"type":20,"tag":28,"props":1502,"children":1505},{"href":1503,"rel":1504},"https://en.wikipedia.org/wiki/Law_of_triviality",[32],[1506],{"type":25,"value":1507},"bike-shedding",{"type":25,"value":1509},", but even so, that debate demonstrates just how many decisions a developer needs to make even during the easiest parts of their day. Best to accept that, for trivial code like ",{"type":20,"tag":60,"props":1511,"children":1513},{"className":1512},[],[1514],{"type":25,"value":1515},"GetPercentageRounds()",{"type":25,"value":1517},", maybe an embarrassingly simple and repetitious solution is just fine, and to save our energy for debating the solutions to the complex and mission-critical problems where the subtleties are more impactful.",{"type":20,"tag":1519,"props":1520,"children":1521},"style",{},[1522],{"type":25,"value":1523},"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":8,"searchDepth":123,"depth":123,"links":1525},[1526,1527,1528],{"id":1025,"depth":114,"text":1028},{"id":1127,"depth":114,"text":1130},{"id":1487,"depth":114,"text":1490},"markdown","content:phendry:2023-01-19:BadCode.md","content","phendry/2023-01-19/BadCode.md","phendry/2023-01-19/BadCode","md",{"user":1536,"name":1537},"phendry","Paul Hendry",{"_path":1539,"_dir":1540,"_draft":7,"_partial":7,"_locale":8,"title":1541,"description":1542,"tags":1543,"image":1544,"publishDate":1540,"excerpt":1542,"body":1545,"_type":1529,"_id":4952,"_source":1531,"_file":4953,"_stem":4954,"_extension":1534,"author":4955},"/phendry/2021-10-30/spotthevulnloopsandtermconditions","2021-10-30","Spot the Vulnerability: Loops and Terminating Conditions","In memory-unsafe languages like C, special care must be taken when copying untrusted data, particularly when copying it to another buffer. In this post, we'll spot and mitigate a past vulnerability in Linux's NTP daemon.",[12,13],"/phendry/2021-10-30/img/vulnerability-2.jpg",{"type":17,"children":1546,"toc":4945},[1547,1570,1576,1581,1594,1792,1840,1845,1851,1856,1861,1916,3593,3598,3604,3630,3664,3669,3974,4007,4186,4191,4323,4328,4565,4606,4619,4631,4637,4649,4896,4901,4907,4941],{"type":20,"tag":21,"props":1548,"children":1549},{},[1550,1552,1559,1561,1568],{"type":25,"value":1551},"In ",{"type":20,"tag":28,"props":1553,"children":1556},{"href":1554,"rel":1555},"https://www.abetterinternet.org/docs/memory-safety/",[32],[1557],{"type":25,"value":1558},"memory-unsafe",{"type":25,"value":1560}," languages like C, special care must be taken when copying untrusted data, particularly when copying it to another buffer. In this post, we'll spot and mitigate a past vulnerability in Linux's ",{"type":20,"tag":28,"props":1562,"children":1565},{"href":1563,"rel":1564},"https://linux.die.net/man/8/ntpd",[32],[1566],{"type":25,"value":1567},"NTP daemon",{"type":25,"value":1569},".",{"type":20,"tag":1023,"props":1571,"children":1573},{"id":1572},"background-buffer-overflows-and-loop-termination",[1574],{"type":25,"value":1575},"Background: Buffer Overflows and Loop Termination",{"type":20,"tag":21,"props":1577,"children":1578},{},[1579],{"type":25,"value":1580},"A buffer overflow occurs when code which intends to write data to a buffer inadvertently writes beyond that buffer into an adjacent memory location. At best this might just invalidate the program's state and cause a crash or other unintended behaviour, but a malicious exploitation of a buffer overflow can often lead to protected data being overwritten by an attacker, leading to denial-of-service or arbitrary code execution.",{"type":20,"tag":21,"props":1582,"children":1583},{},[1584,1586,1592],{"type":25,"value":1585},"A common cause for buffer overflows is a looping construct whose terminating conditions are either invalid or missing. The simplest example of this is a ",{"type":20,"tag":60,"props":1587,"children":1589},{"className":1588},[],[1590],{"type":25,"value":1591},"strcpy()",{"type":25,"value":1593},"-style function like the following, intended to copy a string between source and destination buffers:",{"type":20,"tag":53,"props":1595,"children":1599},{"className":1596,"code":1597,"language":1598,"meta":8,"style":8},"language-c shiki shiki-themes github-light github-dark","char * copy(char *dst, char *src) {\n    char *dst_start = dst;\n\n    while((*dst++ = *src++) != '\\0');\n\n    return dst_start;\n}\n","c",[1600],{"type":20,"tag":60,"props":1601,"children":1602},{"__ignoreMap":8},[1603,1661,1688,1695,1766,1773,1785],{"type":20,"tag":64,"props":1604,"children":1605},{"class":66,"line":67},[1606,1611,1616,1621,1625,1629,1633,1639,1643,1647,1651,1656],{"type":20,"tag":64,"props":1607,"children":1608},{"style":71},[1609],{"type":25,"value":1610},"char",{"type":20,"tag":64,"props":1612,"children":1613},{"style":71},[1614],{"type":25,"value":1615}," *",{"type":20,"tag":64,"props":1617,"children":1618},{"style":87},[1619],{"type":25,"value":1620}," copy",{"type":20,"tag":64,"props":1622,"children":1623},{"style":93},[1624],{"type":25,"value":96},{"type":20,"tag":64,"props":1626,"children":1627},{"style":71},[1628],{"type":25,"value":1610},{"type":20,"tag":64,"props":1630,"children":1631},{"style":71},[1632],{"type":25,"value":1615},{"type":20,"tag":64,"props":1634,"children":1636},{"style":1635},"--shiki-default:#E36209;--shiki-dark:#FFAB70",[1637],{"type":25,"value":1638},"dst",{"type":20,"tag":64,"props":1640,"children":1641},{"style":93},[1642],{"type":25,"value":960},{"type":20,"tag":64,"props":1644,"children":1645},{"style":71},[1646],{"type":25,"value":1610},{"type":20,"tag":64,"props":1648,"children":1649},{"style":71},[1650],{"type":25,"value":1615},{"type":20,"tag":64,"props":1652,"children":1653},{"style":1635},[1654],{"type":25,"value":1655},"src",{"type":20,"tag":64,"props":1657,"children":1658},{"style":93},[1659],{"type":25,"value":1660},") {\n",{"type":20,"tag":64,"props":1662,"children":1663},{"class":66,"line":114},[1664,1669,1673,1678,1683],{"type":20,"tag":64,"props":1665,"children":1666},{"style":71},[1667],{"type":25,"value":1668},"    char",{"type":20,"tag":64,"props":1670,"children":1671},{"style":71},[1672],{"type":25,"value":1615},{"type":20,"tag":64,"props":1674,"children":1675},{"style":93},[1676],{"type":25,"value":1677},"dst_start ",{"type":20,"tag":64,"props":1679,"children":1680},{"style":71},[1681],{"type":25,"value":1682},"=",{"type":20,"tag":64,"props":1684,"children":1685},{"style":93},[1686],{"type":25,"value":1687}," dst;\n",{"type":20,"tag":64,"props":1689,"children":1690},{"class":66,"line":123},[1691],{"type":20,"tag":64,"props":1692,"children":1693},{"emptyLinePlaceholder":703},[1694],{"type":25,"value":706},{"type":20,"tag":64,"props":1696,"children":1697},{"class":66,"line":152},[1698,1703,1708,1712,1716,1721,1725,1729,1733,1737,1742,1747,1752,1757,1762],{"type":20,"tag":64,"props":1699,"children":1700},{"style":71},[1701],{"type":25,"value":1702},"    while",{"type":20,"tag":64,"props":1704,"children":1705},{"style":93},[1706],{"type":25,"value":1707},"((",{"type":20,"tag":64,"props":1709,"children":1710},{"style":71},[1711],{"type":25,"value":893},{"type":20,"tag":64,"props":1713,"children":1714},{"style":93},[1715],{"type":25,"value":1638},{"type":20,"tag":64,"props":1717,"children":1718},{"style":71},[1719],{"type":25,"value":1720},"++",{"type":20,"tag":64,"props":1722,"children":1723},{"style":71},[1724],{"type":25,"value":863},{"type":20,"tag":64,"props":1726,"children":1727},{"style":71},[1728],{"type":25,"value":1615},{"type":20,"tag":64,"props":1730,"children":1731},{"style":93},[1732],{"type":25,"value":1655},{"type":20,"tag":64,"props":1734,"children":1735},{"style":71},[1736],{"type":25,"value":1720},{"type":20,"tag":64,"props":1738,"children":1739},{"style":93},[1740],{"type":25,"value":1741},") ",{"type":20,"tag":64,"props":1743,"children":1744},{"style":71},[1745],{"type":25,"value":1746},"!=",{"type":20,"tag":64,"props":1748,"children":1749},{"style":161},[1750],{"type":25,"value":1751}," '",{"type":20,"tag":64,"props":1753,"children":1754},{"style":142},[1755],{"type":25,"value":1756},"\\0",{"type":20,"tag":64,"props":1758,"children":1759},{"style":161},[1760],{"type":25,"value":1761},"'",{"type":20,"tag":64,"props":1763,"children":1764},{"style":93},[1765],{"type":25,"value":903},{"type":20,"tag":64,"props":1767,"children":1768},{"class":66,"line":172},[1769],{"type":20,"tag":64,"props":1770,"children":1771},{"emptyLinePlaceholder":703},[1772],{"type":25,"value":706},{"type":20,"tag":64,"props":1774,"children":1775},{"class":66,"line":218},[1776,1780],{"type":20,"tag":64,"props":1777,"children":1778},{"style":71},[1779],{"type":25,"value":715},{"type":20,"tag":64,"props":1781,"children":1782},{"style":93},[1783],{"type":25,"value":1784}," dst_start;\n",{"type":20,"tag":64,"props":1786,"children":1787},{"class":66,"line":235},[1788],{"type":20,"tag":64,"props":1789,"children":1790},{"style":93},[1791],{"type":25,"value":733},{"type":20,"tag":21,"props":1793,"children":1794},{},[1795,1797,1802,1804,1809,1811,1817,1819,1824,1826,1831,1833,1838],{"type":25,"value":1796},"The above loop copies from ",{"type":20,"tag":60,"props":1798,"children":1800},{"className":1799},[],[1801],{"type":25,"value":1655},{"type":25,"value":1803}," to ",{"type":20,"tag":60,"props":1805,"children":1807},{"className":1806},[],[1808],{"type":25,"value":1638},{"type":25,"value":1810}," until it sees a ",{"type":20,"tag":60,"props":1812,"children":1814},{"className":1813},[],[1815],{"type":25,"value":1816},"NULL",{"type":25,"value":1818}," character, with no bearing on the size of the ",{"type":20,"tag":60,"props":1820,"children":1822},{"className":1821},[],[1823],{"type":25,"value":1638},{"type":25,"value":1825}," buffer. If ",{"type":20,"tag":60,"props":1827,"children":1829},{"className":1828},[],[1830],{"type":25,"value":1655},{"type":25,"value":1832}," is larger than ",{"type":20,"tag":60,"props":1834,"children":1836},{"className":1835},[],[1837],{"type":25,"value":1638},{"type":25,"value":1839},", this will overrun the buffer.",{"type":20,"tag":21,"props":1841,"children":1842},{},[1843],{"type":25,"value":1844},"While the buffer overflow potential of the above is easy to recognize, it can be much more difficult when complex application logic is mixed in.",{"type":20,"tag":1023,"props":1846,"children":1848},{"id":1847},"processing-a-packet-in-ntpd",[1849],{"type":25,"value":1850},"Processing a Packet in NTPD",{"type":20,"tag":21,"props":1852,"children":1853},{},[1854],{"type":25,"value":1855},"What follows is more-or-less exactly the vulnerable NTPD code, presented in its entirety to help demonstrate how tricky it can be to assess complex loops for correctness.",{"type":20,"tag":21,"props":1857,"children":1858},{},[1859],{"type":25,"value":1860},"In the code below,",{"type":20,"tag":1862,"props":1863,"children":1864},"ul",{},[1865,1876,1887,1898],{"type":20,"tag":1039,"props":1866,"children":1867},{},[1868,1874],{"type":20,"tag":60,"props":1869,"children":1871},{"className":1870},[],[1872],{"type":25,"value":1873},"ctl_getitem()",{"type":25,"value":1875}," is a function which gets the next data item from an incoming NTP packet,",{"type":20,"tag":1039,"props":1877,"children":1878},{},[1879,1885],{"type":20,"tag":60,"props":1880,"children":1882},{"className":1881},[],[1883],{"type":25,"value":1884},"buf",{"type":25,"value":1886}," is the 128-character buffer into which packet data is written,",{"type":20,"tag":1039,"props":1888,"children":1889},{},[1890,1896],{"type":20,"tag":60,"props":1891,"children":1893},{"className":1892},[],[1894],{"type":25,"value":1895},"cp",{"type":25,"value":1897}," is a pointer into the input data (used during the copy), and",{"type":20,"tag":1039,"props":1899,"children":1900},{},[1901,1907,1909,1914],{"type":20,"tag":60,"props":1902,"children":1904},{"className":1903},[],[1905],{"type":25,"value":1906},"tp",{"type":25,"value":1908}," is a pointer into ",{"type":20,"tag":60,"props":1910,"children":1912},{"className":1911},[],[1913],{"type":25,"value":1884},{"type":25,"value":1915}," (also used during the copy).",{"type":20,"tag":53,"props":1917,"children":1919},{"className":1596,"code":1918,"language":1598,"meta":8,"style":8},"static struct ctl_var *\nctl_getitem(\n    struct ctl_var *var_list,\n    char **data\n)\n{\n    register struct ctl_var *v;\n    register char *cp;\n    register char *tp;\n    static struct ctl_var eol = { 0, EOV, };\n    static char buf[128];\n\n    /*\n     * Delete leading commas and white space\n     */\n    while (reqpt \u003C reqend && (*reqpt == ',' || isspace((int)*reqpt))) {\n        reqpt++;\n    }\n\n    if (reqpt >= reqend)\n        return 0;\n\n    if (var_list == (struct c tl_var *)0)\n        return &eol;\n\n    /*\n     * Look for a first character match on the tag. If we find one, see if it is a full match.\n     */\n    v = var_list;\n    cp = reqpt;\n    while (!(v->flags & EOV)) {\n        if (!(v->flags & PADDING) && *cp == *(v->text)) {\n            tp = v->text;\n            while (*tp != '\\0' && *tp != '=' && cp \u003C reqend && *cp == *tp) {\n                cp++;\n                tp++;\n            }\n\n            if ((*tp == '\\0') || (*tp == '=')) {\n                while (cp \u003C reqend && isspace((int)*cp))\n                    cp++;\n\n                if (cp == reqend || *cp == ',') {\n                    buf[0] = '\\0';\n                    *data = buf;\n                    if (cp \u003C reqend)\n                        cp++;\n                    reqpt = cp;\n                    return v;\n                }\n\n                if (*cp == '=') {\n                    cp++;\n                    tp = buf;\n                    while (cp \u003C reqend && isspace((int)*cp))\n                        cp++;\n\n                    while (cp \u003C reqend && *cp != ',')\n                        *tp++ = *cp++;\n                    if (cp \u003C reqend)\n                        cp++;\n                    *tp = '\\0';\n                    while (isspace((int)(*(tp - 1))))\n                        *(--tp) = '\\0';\n\n                    reqpt = cp;\n                    *data = buf;\n                    return v;\n                }\n            }\n            cp = reqpt;\n        }\n        v++;\n    }\n    return v;\n}\n",[1920],{"type":20,"tag":60,"props":1921,"children":1922},{"__ignoreMap":8},[1923,1946,1959,1984,2001,2008,2015,2040,2061,2081,2117,2148,2155,2164,2172,2180,2261,2277,2285,2292,2313,2328,2335,2381,2398,2405,2413,2422,2430,2448,2466,2498,2554,2572,2673,2690,2707,2716,2724,2796,2847,2864,2872,2917,2959,2982,3003,3020,3038,3052,3061,3069,3101,3117,3134,3183,3199,3207,3251,3288,3308,3324,3356,3408,3450,3458,3474,3494,3506,3514,3522,3539,3548,3565,3573,3585],{"type":20,"tag":64,"props":1924,"children":1925},{"class":66,"line":67},[1926,1931,1936,1941],{"type":20,"tag":64,"props":1927,"children":1928},{"style":71},[1929],{"type":25,"value":1930},"static",{"type":20,"tag":64,"props":1932,"children":1933},{"style":71},[1934],{"type":25,"value":1935}," struct",{"type":20,"tag":64,"props":1937,"children":1938},{"style":93},[1939],{"type":25,"value":1940}," ctl_var ",{"type":20,"tag":64,"props":1942,"children":1943},{"style":71},[1944],{"type":25,"value":1945},"*\n",{"type":20,"tag":64,"props":1947,"children":1948},{"class":66,"line":114},[1949,1954],{"type":20,"tag":64,"props":1950,"children":1951},{"style":87},[1952],{"type":25,"value":1953},"ctl_getitem",{"type":20,"tag":64,"props":1955,"children":1956},{"style":93},[1957],{"type":25,"value":1958},"(\n",{"type":20,"tag":64,"props":1960,"children":1961},{"class":66,"line":123},[1962,1967,1971,1975,1980],{"type":20,"tag":64,"props":1963,"children":1964},{"style":71},[1965],{"type":25,"value":1966},"    struct",{"type":20,"tag":64,"props":1968,"children":1969},{"style":93},[1970],{"type":25,"value":1940},{"type":20,"tag":64,"props":1972,"children":1973},{"style":71},[1974],{"type":25,"value":893},{"type":20,"tag":64,"props":1976,"children":1977},{"style":1635},[1978],{"type":25,"value":1979},"var_list",{"type":20,"tag":64,"props":1981,"children":1982},{"style":93},[1983],{"type":25,"value":1219},{"type":20,"tag":64,"props":1985,"children":1986},{"class":66,"line":152},[1987,1991,1996],{"type":20,"tag":64,"props":1988,"children":1989},{"style":71},[1990],{"type":25,"value":1668},{"type":20,"tag":64,"props":1992,"children":1993},{"style":71},[1994],{"type":25,"value":1995}," **",{"type":20,"tag":64,"props":1997,"children":1998},{"style":93},[1999],{"type":25,"value":2000},"data\n",{"type":20,"tag":64,"props":2002,"children":2003},{"class":66,"line":172},[2004],{"type":20,"tag":64,"props":2005,"children":2006},{"style":93},[2007],{"type":25,"value":111},{"type":20,"tag":64,"props":2009,"children":2010},{"class":66,"line":218},[2011],{"type":20,"tag":64,"props":2012,"children":2013},{"style":93},[2014],{"type":25,"value":120},{"type":20,"tag":64,"props":2016,"children":2017},{"class":66,"line":235},[2018,2023,2027,2031,2035],{"type":20,"tag":64,"props":2019,"children":2020},{"style":71},[2021],{"type":25,"value":2022},"    register",{"type":20,"tag":64,"props":2024,"children":2025},{"style":71},[2026],{"type":25,"value":1935},{"type":20,"tag":64,"props":2028,"children":2029},{"style":93},[2030],{"type":25,"value":1940},{"type":20,"tag":64,"props":2032,"children":2033},{"style":71},[2034],{"type":25,"value":893},{"type":20,"tag":64,"props":2036,"children":2037},{"style":93},[2038],{"type":25,"value":2039},"v;\n",{"type":20,"tag":64,"props":2041,"children":2042},{"class":66,"line":276},[2043,2047,2052,2056],{"type":20,"tag":64,"props":2044,"children":2045},{"style":71},[2046],{"type":25,"value":2022},{"type":20,"tag":64,"props":2048,"children":2049},{"style":71},[2050],{"type":25,"value":2051}," char",{"type":20,"tag":64,"props":2053,"children":2054},{"style":71},[2055],{"type":25,"value":1615},{"type":20,"tag":64,"props":2057,"children":2058},{"style":93},[2059],{"type":25,"value":2060},"cp;\n",{"type":20,"tag":64,"props":2062,"children":2063},{"class":66,"line":293},[2064,2068,2072,2076],{"type":20,"tag":64,"props":2065,"children":2066},{"style":71},[2067],{"type":25,"value":2022},{"type":20,"tag":64,"props":2069,"children":2070},{"style":71},[2071],{"type":25,"value":2051},{"type":20,"tag":64,"props":2073,"children":2074},{"style":71},[2075],{"type":25,"value":1615},{"type":20,"tag":64,"props":2077,"children":2078},{"style":93},[2079],{"type":25,"value":2080},"tp;\n",{"type":20,"tag":64,"props":2082,"children":2083},{"class":66,"line":334},[2084,2089,2093,2098,2102,2107,2112],{"type":20,"tag":64,"props":2085,"children":2086},{"style":71},[2087],{"type":25,"value":2088},"    static",{"type":20,"tag":64,"props":2090,"children":2091},{"style":71},[2092],{"type":25,"value":1935},{"type":20,"tag":64,"props":2094,"children":2095},{"style":93},[2096],{"type":25,"value":2097}," ctl_var eol ",{"type":20,"tag":64,"props":2099,"children":2100},{"style":71},[2101],{"type":25,"value":1682},{"type":20,"tag":64,"props":2103,"children":2104},{"style":93},[2105],{"type":25,"value":2106}," { ",{"type":20,"tag":64,"props":2108,"children":2109},{"style":142},[2110],{"type":25,"value":2111},"0",{"type":20,"tag":64,"props":2113,"children":2114},{"style":93},[2115],{"type":25,"value":2116},", EOV, };\n",{"type":20,"tag":64,"props":2118,"children":2119},{"class":66,"line":351},[2120,2124,2128,2133,2138,2143],{"type":20,"tag":64,"props":2121,"children":2122},{"style":71},[2123],{"type":25,"value":2088},{"type":20,"tag":64,"props":2125,"children":2126},{"style":71},[2127],{"type":25,"value":2051},{"type":20,"tag":64,"props":2129,"children":2130},{"style":1635},[2131],{"type":25,"value":2132}," buf",{"type":20,"tag":64,"props":2134,"children":2135},{"style":93},[2136],{"type":25,"value":2137},"[",{"type":20,"tag":64,"props":2139,"children":2140},{"style":142},[2141],{"type":25,"value":2142},"128",{"type":20,"tag":64,"props":2144,"children":2145},{"style":93},[2146],{"type":25,"value":2147},"];\n",{"type":20,"tag":64,"props":2149,"children":2150},{"class":66,"line":392},[2151],{"type":20,"tag":64,"props":2152,"children":2153},{"emptyLinePlaceholder":703},[2154],{"type":25,"value":706},{"type":20,"tag":64,"props":2156,"children":2157},{"class":66,"line":409},[2158],{"type":20,"tag":64,"props":2159,"children":2161},{"style":2160},"--shiki-default:#6A737D;--shiki-dark:#6A737D",[2162],{"type":25,"value":2163},"    /*\n",{"type":20,"tag":64,"props":2165,"children":2166},{"class":66,"line":450},[2167],{"type":20,"tag":64,"props":2168,"children":2169},{"style":2160},[2170],{"type":25,"value":2171},"     * Delete leading commas and white space\n",{"type":20,"tag":64,"props":2173,"children":2174},{"class":66,"line":467},[2175],{"type":20,"tag":64,"props":2176,"children":2177},{"style":2160},[2178],{"type":25,"value":2179},"     */\n",{"type":20,"tag":64,"props":2181,"children":2182},{"class":66,"line":508},[2183,2187,2192,2197,2202,2207,2211,2215,2220,2224,2229,2234,2239,2243,2247,2252,2256],{"type":20,"tag":64,"props":2184,"children":2185},{"style":71},[2186],{"type":25,"value":1702},{"type":20,"tag":64,"props":2188,"children":2189},{"style":93},[2190],{"type":25,"value":2191}," (reqpt ",{"type":20,"tag":64,"props":2193,"children":2194},{"style":71},[2195],{"type":25,"value":2196},"\u003C",{"type":20,"tag":64,"props":2198,"children":2199},{"style":93},[2200],{"type":25,"value":2201}," reqend ",{"type":20,"tag":64,"props":2203,"children":2204},{"style":71},[2205],{"type":25,"value":2206},"&&",{"type":20,"tag":64,"props":2208,"children":2209},{"style":93},[2210],{"type":25,"value":868},{"type":20,"tag":64,"props":2212,"children":2213},{"style":71},[2214],{"type":25,"value":893},{"type":20,"tag":64,"props":2216,"children":2217},{"style":93},[2218],{"type":25,"value":2219},"reqpt ",{"type":20,"tag":64,"props":2221,"children":2222},{"style":71},[2223],{"type":25,"value":139},{"type":20,"tag":64,"props":2225,"children":2226},{"style":161},[2227],{"type":25,"value":2228}," ','",{"type":20,"tag":64,"props":2230,"children":2231},{"style":71},[2232],{"type":25,"value":2233}," ||",{"type":20,"tag":64,"props":2235,"children":2236},{"style":87},[2237],{"type":25,"value":2238}," isspace",{"type":20,"tag":64,"props":2240,"children":2241},{"style":93},[2242],{"type":25,"value":1707},{"type":20,"tag":64,"props":2244,"children":2245},{"style":71},[2246],{"type":25,"value":873},{"type":20,"tag":64,"props":2248,"children":2249},{"style":93},[2250],{"type":25,"value":2251},")",{"type":20,"tag":64,"props":2253,"children":2254},{"style":71},[2255],{"type":25,"value":893},{"type":20,"tag":64,"props":2257,"children":2258},{"style":93},[2259],{"type":25,"value":2260},"reqpt))) {\n",{"type":20,"tag":64,"props":2262,"children":2263},{"class":66,"line":525},[2264,2269,2273],{"type":20,"tag":64,"props":2265,"children":2266},{"style":93},[2267],{"type":25,"value":2268},"        reqpt",{"type":20,"tag":64,"props":2270,"children":2271},{"style":71},[2272],{"type":25,"value":1720},{"type":20,"tag":64,"props":2274,"children":2275},{"style":93},[2276],{"type":25,"value":169},{"type":20,"tag":64,"props":2278,"children":2279},{"class":66,"line":566},[2280],{"type":20,"tag":64,"props":2281,"children":2282},{"style":93},[2283],{"type":25,"value":2284},"    }\n",{"type":20,"tag":64,"props":2286,"children":2287},{"class":66,"line":583},[2288],{"type":20,"tag":64,"props":2289,"children":2290},{"emptyLinePlaceholder":703},[2291],{"type":25,"value":706},{"type":20,"tag":64,"props":2293,"children":2294},{"class":66,"line":624},[2295,2299,2303,2308],{"type":20,"tag":64,"props":2296,"children":2297},{"style":71},[2298],{"type":25,"value":129},{"type":20,"tag":64,"props":2300,"children":2301},{"style":93},[2302],{"type":25,"value":2191},{"type":20,"tag":64,"props":2304,"children":2305},{"style":71},[2306],{"type":25,"value":2307},">=",{"type":20,"tag":64,"props":2309,"children":2310},{"style":93},[2311],{"type":25,"value":2312}," reqend)\n",{"type":20,"tag":64,"props":2314,"children":2315},{"class":66,"line":641},[2316,2320,2324],{"type":20,"tag":64,"props":2317,"children":2318},{"style":71},[2319],{"type":25,"value":158},{"type":20,"tag":64,"props":2321,"children":2322},{"style":142},[2323],{"type":25,"value":145},{"type":20,"tag":64,"props":2325,"children":2326},{"style":93},[2327],{"type":25,"value":169},{"type":20,"tag":64,"props":2329,"children":2330},{"class":66,"line":682},[2331],{"type":20,"tag":64,"props":2332,"children":2333},{"emptyLinePlaceholder":703},[2334],{"type":25,"value":706},{"type":20,"tag":64,"props":2336,"children":2337},{"class":66,"line":699},[2338,2342,2347,2351,2355,2360,2365,2369,2373,2377],{"type":20,"tag":64,"props":2339,"children":2340},{"style":71},[2341],{"type":25,"value":129},{"type":20,"tag":64,"props":2343,"children":2344},{"style":93},[2345],{"type":25,"value":2346}," (var_list ",{"type":20,"tag":64,"props":2348,"children":2349},{"style":71},[2350],{"type":25,"value":139},{"type":20,"tag":64,"props":2352,"children":2353},{"style":93},[2354],{"type":25,"value":868},{"type":20,"tag":64,"props":2356,"children":2357},{"style":71},[2358],{"type":25,"value":2359},"struct",{"type":20,"tag":64,"props":2361,"children":2362},{"style":93},[2363],{"type":25,"value":2364}," c tl_var ",{"type":20,"tag":64,"props":2366,"children":2367},{"style":71},[2368],{"type":25,"value":893},{"type":20,"tag":64,"props":2370,"children":2371},{"style":93},[2372],{"type":25,"value":2251},{"type":20,"tag":64,"props":2374,"children":2375},{"style":142},[2376],{"type":25,"value":2111},{"type":20,"tag":64,"props":2378,"children":2379},{"style":93},[2380],{"type":25,"value":111},{"type":20,"tag":64,"props":2382,"children":2383},{"class":66,"line":709},[2384,2388,2393],{"type":20,"tag":64,"props":2385,"children":2386},{"style":71},[2387],{"type":25,"value":158},{"type":20,"tag":64,"props":2389,"children":2390},{"style":71},[2391],{"type":25,"value":2392}," &",{"type":20,"tag":64,"props":2394,"children":2395},{"style":93},[2396],{"type":25,"value":2397},"eol;\n",{"type":20,"tag":64,"props":2399,"children":2400},{"class":66,"line":727},[2401],{"type":20,"tag":64,"props":2402,"children":2403},{"emptyLinePlaceholder":703},[2404],{"type":25,"value":706},{"type":20,"tag":64,"props":2406,"children":2408},{"class":66,"line":2407},26,[2409],{"type":20,"tag":64,"props":2410,"children":2411},{"style":2160},[2412],{"type":25,"value":2163},{"type":20,"tag":64,"props":2414,"children":2416},{"class":66,"line":2415},27,[2417],{"type":20,"tag":64,"props":2418,"children":2419},{"style":2160},[2420],{"type":25,"value":2421},"     * Look for a first character match on the tag. If we find one, see if it is a full match.\n",{"type":20,"tag":64,"props":2423,"children":2425},{"class":66,"line":2424},28,[2426],{"type":20,"tag":64,"props":2427,"children":2428},{"style":2160},[2429],{"type":25,"value":2179},{"type":20,"tag":64,"props":2431,"children":2433},{"class":66,"line":2432},29,[2434,2439,2443],{"type":20,"tag":64,"props":2435,"children":2436},{"style":93},[2437],{"type":25,"value":2438},"    v ",{"type":20,"tag":64,"props":2440,"children":2441},{"style":71},[2442],{"type":25,"value":1682},{"type":20,"tag":64,"props":2444,"children":2445},{"style":93},[2446],{"type":25,"value":2447}," var_list;\n",{"type":20,"tag":64,"props":2449,"children":2451},{"class":66,"line":2450},30,[2452,2457,2461],{"type":20,"tag":64,"props":2453,"children":2454},{"style":93},[2455],{"type":25,"value":2456},"    cp ",{"type":20,"tag":64,"props":2458,"children":2459},{"style":71},[2460],{"type":25,"value":1682},{"type":20,"tag":64,"props":2462,"children":2463},{"style":93},[2464],{"type":25,"value":2465}," reqpt;\n",{"type":20,"tag":64,"props":2467,"children":2469},{"class":66,"line":2468},31,[2470,2474,2478,2483,2488,2493],{"type":20,"tag":64,"props":2471,"children":2472},{"style":71},[2473],{"type":25,"value":1702},{"type":20,"tag":64,"props":2475,"children":2476},{"style":93},[2477],{"type":25,"value":868},{"type":20,"tag":64,"props":2479,"children":2480},{"style":71},[2481],{"type":25,"value":2482},"!",{"type":20,"tag":64,"props":2484,"children":2485},{"style":93},[2486],{"type":25,"value":2487},"(v->flags ",{"type":20,"tag":64,"props":2489,"children":2490},{"style":71},[2491],{"type":25,"value":2492},"&",{"type":20,"tag":64,"props":2494,"children":2495},{"style":93},[2496],{"type":25,"value":2497}," EOV)) {\n",{"type":20,"tag":64,"props":2499,"children":2501},{"class":66,"line":2500},32,[2502,2507,2511,2515,2519,2523,2528,2532,2536,2541,2545,2549],{"type":20,"tag":64,"props":2503,"children":2504},{"style":71},[2505],{"type":25,"value":2506},"        if",{"type":20,"tag":64,"props":2508,"children":2509},{"style":93},[2510],{"type":25,"value":868},{"type":20,"tag":64,"props":2512,"children":2513},{"style":71},[2514],{"type":25,"value":2482},{"type":20,"tag":64,"props":2516,"children":2517},{"style":93},[2518],{"type":25,"value":2487},{"type":20,"tag":64,"props":2520,"children":2521},{"style":71},[2522],{"type":25,"value":2492},{"type":20,"tag":64,"props":2524,"children":2525},{"style":93},[2526],{"type":25,"value":2527}," PADDING) ",{"type":20,"tag":64,"props":2529,"children":2530},{"style":71},[2531],{"type":25,"value":2206},{"type":20,"tag":64,"props":2533,"children":2534},{"style":71},[2535],{"type":25,"value":1615},{"type":20,"tag":64,"props":2537,"children":2538},{"style":93},[2539],{"type":25,"value":2540},"cp ",{"type":20,"tag":64,"props":2542,"children":2543},{"style":71},[2544],{"type":25,"value":139},{"type":20,"tag":64,"props":2546,"children":2547},{"style":71},[2548],{"type":25,"value":1615},{"type":20,"tag":64,"props":2550,"children":2551},{"style":93},[2552],{"type":25,"value":2553},"(v->text)) {\n",{"type":20,"tag":64,"props":2555,"children":2557},{"class":66,"line":2556},33,[2558,2563,2567],{"type":20,"tag":64,"props":2559,"children":2560},{"style":93},[2561],{"type":25,"value":2562},"            tp ",{"type":20,"tag":64,"props":2564,"children":2565},{"style":71},[2566],{"type":25,"value":1682},{"type":20,"tag":64,"props":2568,"children":2569},{"style":93},[2570],{"type":25,"value":2571}," v->text;\n",{"type":20,"tag":64,"props":2573,"children":2575},{"class":66,"line":2574},34,[2576,2581,2585,2589,2594,2598,2602,2606,2610,2614,2618,2622,2626,2631,2635,2640,2644,2648,2652,2656,2660,2664,2668],{"type":20,"tag":64,"props":2577,"children":2578},{"style":71},[2579],{"type":25,"value":2580},"            while",{"type":20,"tag":64,"props":2582,"children":2583},{"style":93},[2584],{"type":25,"value":868},{"type":20,"tag":64,"props":2586,"children":2587},{"style":71},[2588],{"type":25,"value":893},{"type":20,"tag":64,"props":2590,"children":2591},{"style":93},[2592],{"type":25,"value":2593},"tp ",{"type":20,"tag":64,"props":2595,"children":2596},{"style":71},[2597],{"type":25,"value":1746},{"type":20,"tag":64,"props":2599,"children":2600},{"style":161},[2601],{"type":25,"value":1751},{"type":20,"tag":64,"props":2603,"children":2604},{"style":142},[2605],{"type":25,"value":1756},{"type":20,"tag":64,"props":2607,"children":2608},{"style":161},[2609],{"type":25,"value":1761},{"type":20,"tag":64,"props":2611,"children":2612},{"style":71},[2613],{"type":25,"value":196},{"type":20,"tag":64,"props":2615,"children":2616},{"style":71},[2617],{"type":25,"value":1615},{"type":20,"tag":64,"props":2619,"children":2620},{"style":93},[2621],{"type":25,"value":2593},{"type":20,"tag":64,"props":2623,"children":2624},{"style":71},[2625],{"type":25,"value":1746},{"type":20,"tag":64,"props":2627,"children":2628},{"style":161},[2629],{"type":25,"value":2630}," '='",{"type":20,"tag":64,"props":2632,"children":2633},{"style":71},[2634],{"type":25,"value":196},{"type":20,"tag":64,"props":2636,"children":2637},{"style":93},[2638],{"type":25,"value":2639}," cp ",{"type":20,"tag":64,"props":2641,"children":2642},{"style":71},[2643],{"type":25,"value":2196},{"type":20,"tag":64,"props":2645,"children":2646},{"style":93},[2647],{"type":25,"value":2201},{"type":20,"tag":64,"props":2649,"children":2650},{"style":71},[2651],{"type":25,"value":2206},{"type":20,"tag":64,"props":2653,"children":2654},{"style":71},[2655],{"type":25,"value":1615},{"type":20,"tag":64,"props":2657,"children":2658},{"style":93},[2659],{"type":25,"value":2540},{"type":20,"tag":64,"props":2661,"children":2662},{"style":71},[2663],{"type":25,"value":139},{"type":20,"tag":64,"props":2665,"children":2666},{"style":71},[2667],{"type":25,"value":1615},{"type":20,"tag":64,"props":2669,"children":2670},{"style":93},[2671],{"type":25,"value":2672},"tp) {\n",{"type":20,"tag":64,"props":2674,"children":2676},{"class":66,"line":2675},35,[2677,2682,2686],{"type":20,"tag":64,"props":2678,"children":2679},{"style":93},[2680],{"type":25,"value":2681},"                cp",{"type":20,"tag":64,"props":2683,"children":2684},{"style":71},[2685],{"type":25,"value":1720},{"type":20,"tag":64,"props":2687,"children":2688},{"style":93},[2689],{"type":25,"value":169},{"type":20,"tag":64,"props":2691,"children":2693},{"class":66,"line":2692},36,[2694,2699,2703],{"type":20,"tag":64,"props":2695,"children":2696},{"style":93},[2697],{"type":25,"value":2698},"                tp",{"type":20,"tag":64,"props":2700,"children":2701},{"style":71},[2702],{"type":25,"value":1720},{"type":20,"tag":64,"props":2704,"children":2705},{"style":93},[2706],{"type":25,"value":169},{"type":20,"tag":64,"props":2708,"children":2710},{"class":66,"line":2709},37,[2711],{"type":20,"tag":64,"props":2712,"children":2713},{"style":93},[2714],{"type":25,"value":2715},"            }\n",{"type":20,"tag":64,"props":2717,"children":2719},{"class":66,"line":2718},38,[2720],{"type":20,"tag":64,"props":2721,"children":2722},{"emptyLinePlaceholder":703},[2723],{"type":25,"value":706},{"type":20,"tag":64,"props":2725,"children":2727},{"class":66,"line":2726},39,[2728,2733,2738,2742,2746,2750,2754,2758,2762,2766,2771,2775,2779,2783,2787,2791],{"type":20,"tag":64,"props":2729,"children":2730},{"style":71},[2731],{"type":25,"value":2732},"            if",{"type":20,"tag":64,"props":2734,"children":2735},{"style":93},[2736],{"type":25,"value":2737}," ((",{"type":20,"tag":64,"props":2739,"children":2740},{"style":71},[2741],{"type":25,"value":893},{"type":20,"tag":64,"props":2743,"children":2744},{"style":93},[2745],{"type":25,"value":2593},{"type":20,"tag":64,"props":2747,"children":2748},{"style":71},[2749],{"type":25,"value":139},{"type":20,"tag":64,"props":2751,"children":2752},{"style":161},[2753],{"type":25,"value":1751},{"type":20,"tag":64,"props":2755,"children":2756},{"style":142},[2757],{"type":25,"value":1756},{"type":20,"tag":64,"props":2759,"children":2760},{"style":161},[2761],{"type":25,"value":1761},{"type":20,"tag":64,"props":2763,"children":2764},{"style":93},[2765],{"type":25,"value":1741},{"type":20,"tag":64,"props":2767,"children":2768},{"style":71},[2769],{"type":25,"value":2770},"||",{"type":20,"tag":64,"props":2772,"children":2773},{"style":93},[2774],{"type":25,"value":868},{"type":20,"tag":64,"props":2776,"children":2777},{"style":71},[2778],{"type":25,"value":893},{"type":20,"tag":64,"props":2780,"children":2781},{"style":93},[2782],{"type":25,"value":2593},{"type":20,"tag":64,"props":2784,"children":2785},{"style":71},[2786],{"type":25,"value":139},{"type":20,"tag":64,"props":2788,"children":2789},{"style":161},[2790],{"type":25,"value":2630},{"type":20,"tag":64,"props":2792,"children":2793},{"style":93},[2794],{"type":25,"value":2795},")) {\n",{"type":20,"tag":64,"props":2797,"children":2799},{"class":66,"line":2798},40,[2800,2805,2810,2814,2818,2822,2826,2830,2834,2838,2842],{"type":20,"tag":64,"props":2801,"children":2802},{"style":71},[2803],{"type":25,"value":2804},"                while",{"type":20,"tag":64,"props":2806,"children":2807},{"style":93},[2808],{"type":25,"value":2809}," (cp ",{"type":20,"tag":64,"props":2811,"children":2812},{"style":71},[2813],{"type":25,"value":2196},{"type":20,"tag":64,"props":2815,"children":2816},{"style":93},[2817],{"type":25,"value":2201},{"type":20,"tag":64,"props":2819,"children":2820},{"style":71},[2821],{"type":25,"value":2206},{"type":20,"tag":64,"props":2823,"children":2824},{"style":87},[2825],{"type":25,"value":2238},{"type":20,"tag":64,"props":2827,"children":2828},{"style":93},[2829],{"type":25,"value":1707},{"type":20,"tag":64,"props":2831,"children":2832},{"style":71},[2833],{"type":25,"value":873},{"type":20,"tag":64,"props":2835,"children":2836},{"style":93},[2837],{"type":25,"value":2251},{"type":20,"tag":64,"props":2839,"children":2840},{"style":71},[2841],{"type":25,"value":893},{"type":20,"tag":64,"props":2843,"children":2844},{"style":93},[2845],{"type":25,"value":2846},"cp))\n",{"type":20,"tag":64,"props":2848,"children":2850},{"class":66,"line":2849},41,[2851,2856,2860],{"type":20,"tag":64,"props":2852,"children":2853},{"style":93},[2854],{"type":25,"value":2855},"                    cp",{"type":20,"tag":64,"props":2857,"children":2858},{"style":71},[2859],{"type":25,"value":1720},{"type":20,"tag":64,"props":2861,"children":2862},{"style":93},[2863],{"type":25,"value":169},{"type":20,"tag":64,"props":2865,"children":2867},{"class":66,"line":2866},42,[2868],{"type":20,"tag":64,"props":2869,"children":2870},{"emptyLinePlaceholder":703},[2871],{"type":25,"value":706},{"type":20,"tag":64,"props":2873,"children":2875},{"class":66,"line":2874},43,[2876,2881,2885,2889,2893,2897,2901,2905,2909,2913],{"type":20,"tag":64,"props":2877,"children":2878},{"style":71},[2879],{"type":25,"value":2880},"                if",{"type":20,"tag":64,"props":2882,"children":2883},{"style":93},[2884],{"type":25,"value":2809},{"type":20,"tag":64,"props":2886,"children":2887},{"style":71},[2888],{"type":25,"value":139},{"type":20,"tag":64,"props":2890,"children":2891},{"style":93},[2892],{"type":25,"value":2201},{"type":20,"tag":64,"props":2894,"children":2895},{"style":71},[2896],{"type":25,"value":2770},{"type":20,"tag":64,"props":2898,"children":2899},{"style":71},[2900],{"type":25,"value":1615},{"type":20,"tag":64,"props":2902,"children":2903},{"style":93},[2904],{"type":25,"value":2540},{"type":20,"tag":64,"props":2906,"children":2907},{"style":71},[2908],{"type":25,"value":139},{"type":20,"tag":64,"props":2910,"children":2911},{"style":161},[2912],{"type":25,"value":2228},{"type":20,"tag":64,"props":2914,"children":2915},{"style":93},[2916],{"type":25,"value":1660},{"type":20,"tag":64,"props":2918,"children":2920},{"class":66,"line":2919},44,[2921,2926,2930,2934,2939,2943,2947,2951,2955],{"type":20,"tag":64,"props":2922,"children":2923},{"style":1635},[2924],{"type":25,"value":2925},"                    buf",{"type":20,"tag":64,"props":2927,"children":2928},{"style":93},[2929],{"type":25,"value":2137},{"type":20,"tag":64,"props":2931,"children":2932},{"style":142},[2933],{"type":25,"value":2111},{"type":20,"tag":64,"props":2935,"children":2936},{"style":93},[2937],{"type":25,"value":2938},"] ",{"type":20,"tag":64,"props":2940,"children":2941},{"style":71},[2942],{"type":25,"value":1682},{"type":20,"tag":64,"props":2944,"children":2945},{"style":161},[2946],{"type":25,"value":1751},{"type":20,"tag":64,"props":2948,"children":2949},{"style":142},[2950],{"type":25,"value":1756},{"type":20,"tag":64,"props":2952,"children":2953},{"style":161},[2954],{"type":25,"value":1761},{"type":20,"tag":64,"props":2956,"children":2957},{"style":93},[2958],{"type":25,"value":169},{"type":20,"tag":64,"props":2960,"children":2962},{"class":66,"line":2961},45,[2963,2968,2973,2977],{"type":20,"tag":64,"props":2964,"children":2965},{"style":71},[2966],{"type":25,"value":2967},"                    *",{"type":20,"tag":64,"props":2969,"children":2970},{"style":93},[2971],{"type":25,"value":2972},"data ",{"type":20,"tag":64,"props":2974,"children":2975},{"style":71},[2976],{"type":25,"value":1682},{"type":20,"tag":64,"props":2978,"children":2979},{"style":93},[2980],{"type":25,"value":2981}," buf;\n",{"type":20,"tag":64,"props":2983,"children":2985},{"class":66,"line":2984},46,[2986,2991,2995,2999],{"type":20,"tag":64,"props":2987,"children":2988},{"style":71},[2989],{"type":25,"value":2990},"                    if",{"type":20,"tag":64,"props":2992,"children":2993},{"style":93},[2994],{"type":25,"value":2809},{"type":20,"tag":64,"props":2996,"children":2997},{"style":71},[2998],{"type":25,"value":2196},{"type":20,"tag":64,"props":3000,"children":3001},{"style":93},[3002],{"type":25,"value":2312},{"type":20,"tag":64,"props":3004,"children":3006},{"class":66,"line":3005},47,[3007,3012,3016],{"type":20,"tag":64,"props":3008,"children":3009},{"style":93},[3010],{"type":25,"value":3011},"                        cp",{"type":20,"tag":64,"props":3013,"children":3014},{"style":71},[3015],{"type":25,"value":1720},{"type":20,"tag":64,"props":3017,"children":3018},{"style":93},[3019],{"type":25,"value":169},{"type":20,"tag":64,"props":3021,"children":3023},{"class":66,"line":3022},48,[3024,3029,3033],{"type":20,"tag":64,"props":3025,"children":3026},{"style":93},[3027],{"type":25,"value":3028},"                    reqpt ",{"type":20,"tag":64,"props":3030,"children":3031},{"style":71},[3032],{"type":25,"value":1682},{"type":20,"tag":64,"props":3034,"children":3035},{"style":93},[3036],{"type":25,"value":3037}," cp;\n",{"type":20,"tag":64,"props":3039,"children":3041},{"class":66,"line":3040},49,[3042,3047],{"type":20,"tag":64,"props":3043,"children":3044},{"style":71},[3045],{"type":25,"value":3046},"                    return",{"type":20,"tag":64,"props":3048,"children":3049},{"style":93},[3050],{"type":25,"value":3051}," v;\n",{"type":20,"tag":64,"props":3053,"children":3055},{"class":66,"line":3054},50,[3056],{"type":20,"tag":64,"props":3057,"children":3058},{"style":93},[3059],{"type":25,"value":3060},"                }\n",{"type":20,"tag":64,"props":3062,"children":3064},{"class":66,"line":3063},51,[3065],{"type":20,"tag":64,"props":3066,"children":3067},{"emptyLinePlaceholder":703},[3068],{"type":25,"value":706},{"type":20,"tag":64,"props":3070,"children":3072},{"class":66,"line":3071},52,[3073,3077,3081,3085,3089,3093,3097],{"type":20,"tag":64,"props":3074,"children":3075},{"style":71},[3076],{"type":25,"value":2880},{"type":20,"tag":64,"props":3078,"children":3079},{"style":93},[3080],{"type":25,"value":868},{"type":20,"tag":64,"props":3082,"children":3083},{"style":71},[3084],{"type":25,"value":893},{"type":20,"tag":64,"props":3086,"children":3087},{"style":93},[3088],{"type":25,"value":2540},{"type":20,"tag":64,"props":3090,"children":3091},{"style":71},[3092],{"type":25,"value":139},{"type":20,"tag":64,"props":3094,"children":3095},{"style":161},[3096],{"type":25,"value":2630},{"type":20,"tag":64,"props":3098,"children":3099},{"style":93},[3100],{"type":25,"value":1660},{"type":20,"tag":64,"props":3102,"children":3104},{"class":66,"line":3103},53,[3105,3109,3113],{"type":20,"tag":64,"props":3106,"children":3107},{"style":93},[3108],{"type":25,"value":2855},{"type":20,"tag":64,"props":3110,"children":3111},{"style":71},[3112],{"type":25,"value":1720},{"type":20,"tag":64,"props":3114,"children":3115},{"style":93},[3116],{"type":25,"value":169},{"type":20,"tag":64,"props":3118,"children":3120},{"class":66,"line":3119},54,[3121,3126,3130],{"type":20,"tag":64,"props":3122,"children":3123},{"style":93},[3124],{"type":25,"value":3125},"                    tp ",{"type":20,"tag":64,"props":3127,"children":3128},{"style":71},[3129],{"type":25,"value":1682},{"type":20,"tag":64,"props":3131,"children":3132},{"style":93},[3133],{"type":25,"value":2981},{"type":20,"tag":64,"props":3135,"children":3137},{"class":66,"line":3136},55,[3138,3143,3147,3151,3155,3159,3163,3167,3171,3175,3179],{"type":20,"tag":64,"props":3139,"children":3140},{"style":71},[3141],{"type":25,"value":3142},"                    while",{"type":20,"tag":64,"props":3144,"children":3145},{"style":93},[3146],{"type":25,"value":2809},{"type":20,"tag":64,"props":3148,"children":3149},{"style":71},[3150],{"type":25,"value":2196},{"type":20,"tag":64,"props":3152,"children":3153},{"style":93},[3154],{"type":25,"value":2201},{"type":20,"tag":64,"props":3156,"children":3157},{"style":71},[3158],{"type":25,"value":2206},{"type":20,"tag":64,"props":3160,"children":3161},{"style":87},[3162],{"type":25,"value":2238},{"type":20,"tag":64,"props":3164,"children":3165},{"style":93},[3166],{"type":25,"value":1707},{"type":20,"tag":64,"props":3168,"children":3169},{"style":71},[3170],{"type":25,"value":873},{"type":20,"tag":64,"props":3172,"children":3173},{"style":93},[3174],{"type":25,"value":2251},{"type":20,"tag":64,"props":3176,"children":3177},{"style":71},[3178],{"type":25,"value":893},{"type":20,"tag":64,"props":3180,"children":3181},{"style":93},[3182],{"type":25,"value":2846},{"type":20,"tag":64,"props":3184,"children":3186},{"class":66,"line":3185},56,[3187,3191,3195],{"type":20,"tag":64,"props":3188,"children":3189},{"style":93},[3190],{"type":25,"value":3011},{"type":20,"tag":64,"props":3192,"children":3193},{"style":71},[3194],{"type":25,"value":1720},{"type":20,"tag":64,"props":3196,"children":3197},{"style":93},[3198],{"type":25,"value":169},{"type":20,"tag":64,"props":3200,"children":3202},{"class":66,"line":3201},57,[3203],{"type":20,"tag":64,"props":3204,"children":3205},{"emptyLinePlaceholder":703},[3206],{"type":25,"value":706},{"type":20,"tag":64,"props":3208,"children":3210},{"class":66,"line":3209},58,[3211,3215,3219,3223,3227,3231,3235,3239,3243,3247],{"type":20,"tag":64,"props":3212,"children":3213},{"style":71},[3214],{"type":25,"value":3142},{"type":20,"tag":64,"props":3216,"children":3217},{"style":93},[3218],{"type":25,"value":2809},{"type":20,"tag":64,"props":3220,"children":3221},{"style":71},[3222],{"type":25,"value":2196},{"type":20,"tag":64,"props":3224,"children":3225},{"style":93},[3226],{"type":25,"value":2201},{"type":20,"tag":64,"props":3228,"children":3229},{"style":71},[3230],{"type":25,"value":2206},{"type":20,"tag":64,"props":3232,"children":3233},{"style":71},[3234],{"type":25,"value":1615},{"type":20,"tag":64,"props":3236,"children":3237},{"style":93},[3238],{"type":25,"value":2540},{"type":20,"tag":64,"props":3240,"children":3241},{"style":71},[3242],{"type":25,"value":1746},{"type":20,"tag":64,"props":3244,"children":3245},{"style":161},[3246],{"type":25,"value":2228},{"type":20,"tag":64,"props":3248,"children":3249},{"style":93},[3250],{"type":25,"value":111},{"type":20,"tag":64,"props":3252,"children":3254},{"class":66,"line":3253},59,[3255,3260,3264,3268,3272,3276,3280,3284],{"type":20,"tag":64,"props":3256,"children":3257},{"style":71},[3258],{"type":25,"value":3259},"                        *",{"type":20,"tag":64,"props":3261,"children":3262},{"style":93},[3263],{"type":25,"value":1906},{"type":20,"tag":64,"props":3265,"children":3266},{"style":71},[3267],{"type":25,"value":1720},{"type":20,"tag":64,"props":3269,"children":3270},{"style":71},[3271],{"type":25,"value":863},{"type":20,"tag":64,"props":3273,"children":3274},{"style":71},[3275],{"type":25,"value":1615},{"type":20,"tag":64,"props":3277,"children":3278},{"style":93},[3279],{"type":25,"value":1895},{"type":20,"tag":64,"props":3281,"children":3282},{"style":71},[3283],{"type":25,"value":1720},{"type":20,"tag":64,"props":3285,"children":3286},{"style":93},[3287],{"type":25,"value":169},{"type":20,"tag":64,"props":3289,"children":3291},{"class":66,"line":3290},60,[3292,3296,3300,3304],{"type":20,"tag":64,"props":3293,"children":3294},{"style":71},[3295],{"type":25,"value":2990},{"type":20,"tag":64,"props":3297,"children":3298},{"style":93},[3299],{"type":25,"value":2809},{"type":20,"tag":64,"props":3301,"children":3302},{"style":71},[3303],{"type":25,"value":2196},{"type":20,"tag":64,"props":3305,"children":3306},{"style":93},[3307],{"type":25,"value":2312},{"type":20,"tag":64,"props":3309,"children":3311},{"class":66,"line":3310},61,[3312,3316,3320],{"type":20,"tag":64,"props":3313,"children":3314},{"style":93},[3315],{"type":25,"value":3011},{"type":20,"tag":64,"props":3317,"children":3318},{"style":71},[3319],{"type":25,"value":1720},{"type":20,"tag":64,"props":3321,"children":3322},{"style":93},[3323],{"type":25,"value":169},{"type":20,"tag":64,"props":3325,"children":3327},{"class":66,"line":3326},62,[3328,3332,3336,3340,3344,3348,3352],{"type":20,"tag":64,"props":3329,"children":3330},{"style":71},[3331],{"type":25,"value":2967},{"type":20,"tag":64,"props":3333,"children":3334},{"style":93},[3335],{"type":25,"value":2593},{"type":20,"tag":64,"props":3337,"children":3338},{"style":71},[3339],{"type":25,"value":1682},{"type":20,"tag":64,"props":3341,"children":3342},{"style":161},[3343],{"type":25,"value":1751},{"type":20,"tag":64,"props":3345,"children":3346},{"style":142},[3347],{"type":25,"value":1756},{"type":20,"tag":64,"props":3349,"children":3350},{"style":161},[3351],{"type":25,"value":1761},{"type":20,"tag":64,"props":3353,"children":3354},{"style":93},[3355],{"type":25,"value":169},{"type":20,"tag":64,"props":3357,"children":3359},{"class":66,"line":3358},63,[3360,3364,3368,3373,3377,3381,3386,3390,3395,3399,3403],{"type":20,"tag":64,"props":3361,"children":3362},{"style":71},[3363],{"type":25,"value":3142},{"type":20,"tag":64,"props":3365,"children":3366},{"style":93},[3367],{"type":25,"value":868},{"type":20,"tag":64,"props":3369,"children":3370},{"style":87},[3371],{"type":25,"value":3372},"isspace",{"type":20,"tag":64,"props":3374,"children":3375},{"style":93},[3376],{"type":25,"value":1707},{"type":20,"tag":64,"props":3378,"children":3379},{"style":71},[3380],{"type":25,"value":873},{"type":20,"tag":64,"props":3382,"children":3383},{"style":93},[3384],{"type":25,"value":3385},")(",{"type":20,"tag":64,"props":3387,"children":3388},{"style":71},[3389],{"type":25,"value":893},{"type":20,"tag":64,"props":3391,"children":3392},{"style":93},[3393],{"type":25,"value":3394},"(tp ",{"type":20,"tag":64,"props":3396,"children":3397},{"style":71},[3398],{"type":25,"value":1438},{"type":20,"tag":64,"props":3400,"children":3401},{"style":142},[3402],{"type":25,"value":1443},{"type":20,"tag":64,"props":3404,"children":3405},{"style":93},[3406],{"type":25,"value":3407},"))))\n",{"type":20,"tag":64,"props":3409,"children":3411},{"class":66,"line":3410},64,[3412,3416,3420,3425,3430,3434,3438,3442,3446],{"type":20,"tag":64,"props":3413,"children":3414},{"style":71},[3415],{"type":25,"value":3259},{"type":20,"tag":64,"props":3417,"children":3418},{"style":93},[3419],{"type":25,"value":96},{"type":20,"tag":64,"props":3421,"children":3422},{"style":71},[3423],{"type":25,"value":3424},"--",{"type":20,"tag":64,"props":3426,"children":3427},{"style":93},[3428],{"type":25,"value":3429},"tp) ",{"type":20,"tag":64,"props":3431,"children":3432},{"style":71},[3433],{"type":25,"value":1682},{"type":20,"tag":64,"props":3435,"children":3436},{"style":161},[3437],{"type":25,"value":1751},{"type":20,"tag":64,"props":3439,"children":3440},{"style":142},[3441],{"type":25,"value":1756},{"type":20,"tag":64,"props":3443,"children":3444},{"style":161},[3445],{"type":25,"value":1761},{"type":20,"tag":64,"props":3447,"children":3448},{"style":93},[3449],{"type":25,"value":169},{"type":20,"tag":64,"props":3451,"children":3453},{"class":66,"line":3452},65,[3454],{"type":20,"tag":64,"props":3455,"children":3456},{"emptyLinePlaceholder":703},[3457],{"type":25,"value":706},{"type":20,"tag":64,"props":3459,"children":3461},{"class":66,"line":3460},66,[3462,3466,3470],{"type":20,"tag":64,"props":3463,"children":3464},{"style":93},[3465],{"type":25,"value":3028},{"type":20,"tag":64,"props":3467,"children":3468},{"style":71},[3469],{"type":25,"value":1682},{"type":20,"tag":64,"props":3471,"children":3472},{"style":93},[3473],{"type":25,"value":3037},{"type":20,"tag":64,"props":3475,"children":3477},{"class":66,"line":3476},67,[3478,3482,3486,3490],{"type":20,"tag":64,"props":3479,"children":3480},{"style":71},[3481],{"type":25,"value":2967},{"type":20,"tag":64,"props":3483,"children":3484},{"style":93},[3485],{"type":25,"value":2972},{"type":20,"tag":64,"props":3487,"children":3488},{"style":71},[3489],{"type":25,"value":1682},{"type":20,"tag":64,"props":3491,"children":3492},{"style":93},[3493],{"type":25,"value":2981},{"type":20,"tag":64,"props":3495,"children":3497},{"class":66,"line":3496},68,[3498,3502],{"type":20,"tag":64,"props":3499,"children":3500},{"style":71},[3501],{"type":25,"value":3046},{"type":20,"tag":64,"props":3503,"children":3504},{"style":93},[3505],{"type":25,"value":3051},{"type":20,"tag":64,"props":3507,"children":3509},{"class":66,"line":3508},69,[3510],{"type":20,"tag":64,"props":3511,"children":3512},{"style":93},[3513],{"type":25,"value":3060},{"type":20,"tag":64,"props":3515,"children":3517},{"class":66,"line":3516},70,[3518],{"type":20,"tag":64,"props":3519,"children":3520},{"style":93},[3521],{"type":25,"value":2715},{"type":20,"tag":64,"props":3523,"children":3525},{"class":66,"line":3524},71,[3526,3531,3535],{"type":20,"tag":64,"props":3527,"children":3528},{"style":93},[3529],{"type":25,"value":3530},"            cp ",{"type":20,"tag":64,"props":3532,"children":3533},{"style":71},[3534],{"type":25,"value":1682},{"type":20,"tag":64,"props":3536,"children":3537},{"style":93},[3538],{"type":25,"value":2465},{"type":20,"tag":64,"props":3540,"children":3542},{"class":66,"line":3541},72,[3543],{"type":20,"tag":64,"props":3544,"children":3545},{"style":93},[3546],{"type":25,"value":3547},"        }\n",{"type":20,"tag":64,"props":3549,"children":3551},{"class":66,"line":3550},73,[3552,3557,3561],{"type":20,"tag":64,"props":3553,"children":3554},{"style":93},[3555],{"type":25,"value":3556},"        v",{"type":20,"tag":64,"props":3558,"children":3559},{"style":71},[3560],{"type":25,"value":1720},{"type":20,"tag":64,"props":3562,"children":3563},{"style":93},[3564],{"type":25,"value":169},{"type":20,"tag":64,"props":3566,"children":3568},{"class":66,"line":3567},74,[3569],{"type":20,"tag":64,"props":3570,"children":3571},{"style":93},[3572],{"type":25,"value":2284},{"type":20,"tag":64,"props":3574,"children":3576},{"class":66,"line":3575},75,[3577,3581],{"type":20,"tag":64,"props":3578,"children":3579},{"style":71},[3580],{"type":25,"value":715},{"type":20,"tag":64,"props":3582,"children":3583},{"style":93},[3584],{"type":25,"value":3051},{"type":20,"tag":64,"props":3586,"children":3588},{"class":66,"line":3587},76,[3589],{"type":20,"tag":64,"props":3590,"children":3591},{"style":93},[3592],{"type":25,"value":733},{"type":20,"tag":21,"props":3594,"children":3595},{},[3596],{"type":25,"value":3597},"Feel free to pause here and try to identify a problem in this function unassisted, otherwise continue on and we'll break it down in detail.",{"type":20,"tag":1023,"props":3599,"children":3601},{"id":3600},"spotting-the-vulnerability",[3602],{"type":25,"value":3603},"Spotting the Vulnerability",{"type":20,"tag":21,"props":3605,"children":3606},{},[3607,3609,3614,3616,3621,3623,3628],{"type":25,"value":3608},"Taking the perspective of an attacker is an effective way of switching from the typical development mindset of \"should this work correctly?\" to the mindset of \"can this work ",{"type":20,"tag":776,"props":3610,"children":3611},{},[3612],{"type":25,"value":3613},"incorrectly?",{"type":25,"value":3615},"\" As an attacker who is ",{"type":20,"tag":776,"props":3617,"children":3618},{},[3619],{"type":25,"value":3620},"trying",{"type":25,"value":3622}," to overrun ",{"type":20,"tag":60,"props":3624,"children":3626},{"className":3625},[],[3627],{"type":25,"value":1884},{"type":25,"value":3629},", your goals would be to",{"type":20,"tag":1035,"props":3631,"children":3632},{},[3633,3652],{"type":20,"tag":1039,"props":3634,"children":3635},{},[3636,3638,3643,3645,3650],{"type":25,"value":3637},"reach the code where ",{"type":20,"tag":60,"props":3639,"children":3641},{"className":3640},[],[3642],{"type":25,"value":1884},{"type":25,"value":3644}," gets written to via the ",{"type":20,"tag":60,"props":3646,"children":3648},{"className":3647},[],[3649],{"type":25,"value":1906},{"type":25,"value":3651}," pointer, and",{"type":20,"tag":1039,"props":3653,"children":3654},{},[3655,3657,3662],{"type":25,"value":3656},"find a means to increment ",{"type":20,"tag":60,"props":3658,"children":3660},{"className":3659},[],[3661],{"type":25,"value":1906},{"type":25,"value":3663}," 128 or more times.",{"type":20,"tag":21,"props":3665,"children":3666},{},[3667],{"type":25,"value":3668},"Starting with this first goal, we first have",{"type":20,"tag":53,"props":3670,"children":3672},{"className":1596,"code":3671,"language":1598,"meta":8,"style":8},"tp = v->text;\nwhile (*tp != '\\0' && *tp != '=' && cp \u003C reqend && *cp == *tp) {\n    cp++;\n    tp++;\n}\n\nif ((*tp == '\\0') || (*tp == '=')) {\n    while (cp \u003C reqend && isspace((int)*cp))\n        cp++;\n",[3673],{"type":20,"tag":60,"props":3674,"children":3675},{"__ignoreMap":8},[3676,3702,3798,3814,3830,3837,3844,3911,3958],{"type":20,"tag":64,"props":3677,"children":3678},{"class":66,"line":67},[3679,3683,3687,3692,3697],{"type":20,"tag":64,"props":3680,"children":3681},{"style":93},[3682],{"type":25,"value":2593},{"type":20,"tag":64,"props":3684,"children":3685},{"style":71},[3686],{"type":25,"value":1682},{"type":20,"tag":64,"props":3688,"children":3689},{"style":93},[3690],{"type":25,"value":3691}," v",{"type":20,"tag":64,"props":3693,"children":3694},{"style":71},[3695],{"type":25,"value":3696},"->",{"type":20,"tag":64,"props":3698,"children":3699},{"style":93},[3700],{"type":25,"value":3701},"text;\n",{"type":20,"tag":64,"props":3703,"children":3704},{"class":66,"line":114},[3705,3710,3714,3718,3722,3726,3730,3734,3738,3742,3746,3750,3754,3758,3762,3766,3770,3774,3778,3782,3786,3790,3794],{"type":20,"tag":64,"props":3706,"children":3707},{"style":71},[3708],{"type":25,"value":3709},"while",{"type":20,"tag":64,"props":3711,"children":3712},{"style":93},[3713],{"type":25,"value":868},{"type":20,"tag":64,"props":3715,"children":3716},{"style":71},[3717],{"type":25,"value":893},{"type":20,"tag":64,"props":3719,"children":3720},{"style":93},[3721],{"type":25,"value":2593},{"type":20,"tag":64,"props":3723,"children":3724},{"style":71},[3725],{"type":25,"value":1746},{"type":20,"tag":64,"props":3727,"children":3728},{"style":161},[3729],{"type":25,"value":1751},{"type":20,"tag":64,"props":3731,"children":3732},{"style":142},[3733],{"type":25,"value":1756},{"type":20,"tag":64,"props":3735,"children":3736},{"style":161},[3737],{"type":25,"value":1761},{"type":20,"tag":64,"props":3739,"children":3740},{"style":71},[3741],{"type":25,"value":196},{"type":20,"tag":64,"props":3743,"children":3744},{"style":71},[3745],{"type":25,"value":1615},{"type":20,"tag":64,"props":3747,"children":3748},{"style":93},[3749],{"type":25,"value":2593},{"type":20,"tag":64,"props":3751,"children":3752},{"style":71},[3753],{"type":25,"value":1746},{"type":20,"tag":64,"props":3755,"children":3756},{"style":161},[3757],{"type":25,"value":2630},{"type":20,"tag":64,"props":3759,"children":3760},{"style":71},[3761],{"type":25,"value":196},{"type":20,"tag":64,"props":3763,"children":3764},{"style":93},[3765],{"type":25,"value":2639},{"type":20,"tag":64,"props":3767,"children":3768},{"style":71},[3769],{"type":25,"value":2196},{"type":20,"tag":64,"props":3771,"children":3772},{"style":93},[3773],{"type":25,"value":2201},{"type":20,"tag":64,"props":3775,"children":3776},{"style":71},[3777],{"type":25,"value":2206},{"type":20,"tag":64,"props":3779,"children":3780},{"style":71},[3781],{"type":25,"value":1615},{"type":20,"tag":64,"props":3783,"children":3784},{"style":93},[3785],{"type":25,"value":2540},{"type":20,"tag":64,"props":3787,"children":3788},{"style":71},[3789],{"type":25,"value":139},{"type":20,"tag":64,"props":3791,"children":3792},{"style":71},[3793],{"type":25,"value":1615},{"type":20,"tag":64,"props":3795,"children":3796},{"style":93},[3797],{"type":25,"value":2672},{"type":20,"tag":64,"props":3799,"children":3800},{"class":66,"line":123},[3801,3806,3810],{"type":20,"tag":64,"props":3802,"children":3803},{"style":93},[3804],{"type":25,"value":3805},"    cp",{"type":20,"tag":64,"props":3807,"children":3808},{"style":71},[3809],{"type":25,"value":1720},{"type":20,"tag":64,"props":3811,"children":3812},{"style":93},[3813],{"type":25,"value":169},{"type":20,"tag":64,"props":3815,"children":3816},{"class":66,"line":152},[3817,3822,3826],{"type":20,"tag":64,"props":3818,"children":3819},{"style":93},[3820],{"type":25,"value":3821},"    tp",{"type":20,"tag":64,"props":3823,"children":3824},{"style":71},[3825],{"type":25,"value":1720},{"type":20,"tag":64,"props":3827,"children":3828},{"style":93},[3829],{"type":25,"value":169},{"type":20,"tag":64,"props":3831,"children":3832},{"class":66,"line":172},[3833],{"type":20,"tag":64,"props":3834,"children":3835},{"style":93},[3836],{"type":25,"value":733},{"type":20,"tag":64,"props":3838,"children":3839},{"class":66,"line":218},[3840],{"type":20,"tag":64,"props":3841,"children":3842},{"emptyLinePlaceholder":703},[3843],{"type":25,"value":706},{"type":20,"tag":64,"props":3845,"children":3846},{"class":66,"line":235},[3847,3851,3855,3859,3863,3867,3871,3875,3879,3883,3887,3891,3895,3899,3903,3907],{"type":20,"tag":64,"props":3848,"children":3849},{"style":71},[3850],{"type":25,"value":772},{"type":20,"tag":64,"props":3852,"children":3853},{"style":93},[3854],{"type":25,"value":2737},{"type":20,"tag":64,"props":3856,"children":3857},{"style":71},[3858],{"type":25,"value":893},{"type":20,"tag":64,"props":3860,"children":3861},{"style":93},[3862],{"type":25,"value":2593},{"type":20,"tag":64,"props":3864,"children":3865},{"style":71},[3866],{"type":25,"value":139},{"type":20,"tag":64,"props":3868,"children":3869},{"style":161},[3870],{"type":25,"value":1751},{"type":20,"tag":64,"props":3872,"children":3873},{"style":142},[3874],{"type":25,"value":1756},{"type":20,"tag":64,"props":3876,"children":3877},{"style":161},[3878],{"type":25,"value":1761},{"type":20,"tag":64,"props":3880,"children":3881},{"style":93},[3882],{"type":25,"value":1741},{"type":20,"tag":64,"props":3884,"children":3885},{"style":71},[3886],{"type":25,"value":2770},{"type":20,"tag":64,"props":3888,"children":3889},{"style":93},[3890],{"type":25,"value":868},{"type":20,"tag":64,"props":3892,"children":3893},{"style":71},[3894],{"type":25,"value":893},{"type":20,"tag":64,"props":3896,"children":3897},{"style":93},[3898],{"type":25,"value":2593},{"type":20,"tag":64,"props":3900,"children":3901},{"style":71},[3902],{"type":25,"value":139},{"type":20,"tag":64,"props":3904,"children":3905},{"style":161},[3906],{"type":25,"value":2630},{"type":20,"tag":64,"props":3908,"children":3909},{"style":93},[3910],{"type":25,"value":2795},{"type":20,"tag":64,"props":3912,"children":3913},{"class":66,"line":276},[3914,3918,3922,3926,3930,3934,3938,3942,3946,3950,3954],{"type":20,"tag":64,"props":3915,"children":3916},{"style":71},[3917],{"type":25,"value":1702},{"type":20,"tag":64,"props":3919,"children":3920},{"style":93},[3921],{"type":25,"value":2809},{"type":20,"tag":64,"props":3923,"children":3924},{"style":71},[3925],{"type":25,"value":2196},{"type":20,"tag":64,"props":3927,"children":3928},{"style":93},[3929],{"type":25,"value":2201},{"type":20,"tag":64,"props":3931,"children":3932},{"style":71},[3933],{"type":25,"value":2206},{"type":20,"tag":64,"props":3935,"children":3936},{"style":87},[3937],{"type":25,"value":2238},{"type":20,"tag":64,"props":3939,"children":3940},{"style":93},[3941],{"type":25,"value":1707},{"type":20,"tag":64,"props":3943,"children":3944},{"style":71},[3945],{"type":25,"value":873},{"type":20,"tag":64,"props":3947,"children":3948},{"style":93},[3949],{"type":25,"value":2251},{"type":20,"tag":64,"props":3951,"children":3952},{"style":71},[3953],{"type":25,"value":893},{"type":20,"tag":64,"props":3955,"children":3956},{"style":93},[3957],{"type":25,"value":2846},{"type":20,"tag":64,"props":3959,"children":3960},{"class":66,"line":293},[3961,3966,3970],{"type":20,"tag":64,"props":3962,"children":3963},{"style":93},[3964],{"type":25,"value":3965},"        cp",{"type":20,"tag":64,"props":3967,"children":3968},{"style":71},[3969],{"type":25,"value":1720},{"type":20,"tag":64,"props":3971,"children":3972},{"style":93},[3973],{"type":25,"value":169},{"type":20,"tag":21,"props":3975,"children":3976},{},[3977,3979,3984,3986,3991,3993,3998,4000,4005],{"type":25,"value":3978},"While looping through variables definitions in order to look for one which matches the input data, we're initially using ",{"type":20,"tag":60,"props":3980,"children":3982},{"className":3981},[],[3983],{"type":25,"value":1906},{"type":25,"value":3985}," as a pointer into the variable's ",{"type":20,"tag":60,"props":3987,"children":3989},{"className":3988},[],[3990],{"type":25,"value":25},{"type":25,"value":3992}," field. If the input matches that text up until a ",{"type":20,"tag":60,"props":3994,"children":3996},{"className":3995},[],[3997],{"type":25,"value":1816},{"type":25,"value":3999}," or ",{"type":20,"tag":60,"props":4001,"children":4003},{"className":4002},[],[4004],{"type":25,"value":1682},{"type":25,"value":4006}," character, this block gets executed. Next,",{"type":20,"tag":53,"props":4008,"children":4010},{"className":1596,"code":4009,"language":1598,"meta":8,"style":8},"    if (cp == reqend || *cp == ',') {\n        buf[0] = '\\0';\n        *data = buf;\n        if (cp \u003C reqend)\n            cp++;\n        reqpt = cp;\n        return v;\n    }\n",[4011],{"type":20,"tag":60,"props":4012,"children":4013},{"__ignoreMap":8},[4014,4057,4097,4117,4136,4152,4168,4179],{"type":20,"tag":64,"props":4015,"children":4016},{"class":66,"line":67},[4017,4021,4025,4029,4033,4037,4041,4045,4049,4053],{"type":20,"tag":64,"props":4018,"children":4019},{"style":71},[4020],{"type":25,"value":129},{"type":20,"tag":64,"props":4022,"children":4023},{"style":93},[4024],{"type":25,"value":2809},{"type":20,"tag":64,"props":4026,"children":4027},{"style":71},[4028],{"type":25,"value":139},{"type":20,"tag":64,"props":4030,"children":4031},{"style":93},[4032],{"type":25,"value":2201},{"type":20,"tag":64,"props":4034,"children":4035},{"style":71},[4036],{"type":25,"value":2770},{"type":20,"tag":64,"props":4038,"children":4039},{"style":71},[4040],{"type":25,"value":1615},{"type":20,"tag":64,"props":4042,"children":4043},{"style":93},[4044],{"type":25,"value":2540},{"type":20,"tag":64,"props":4046,"children":4047},{"style":71},[4048],{"type":25,"value":139},{"type":20,"tag":64,"props":4050,"children":4051},{"style":161},[4052],{"type":25,"value":2228},{"type":20,"tag":64,"props":4054,"children":4055},{"style":93},[4056],{"type":25,"value":1660},{"type":20,"tag":64,"props":4058,"children":4059},{"class":66,"line":114},[4060,4065,4069,4073,4077,4081,4085,4089,4093],{"type":20,"tag":64,"props":4061,"children":4062},{"style":1635},[4063],{"type":25,"value":4064},"        buf",{"type":20,"tag":64,"props":4066,"children":4067},{"style":93},[4068],{"type":25,"value":2137},{"type":20,"tag":64,"props":4070,"children":4071},{"style":142},[4072],{"type":25,"value":2111},{"type":20,"tag":64,"props":4074,"children":4075},{"style":93},[4076],{"type":25,"value":2938},{"type":20,"tag":64,"props":4078,"children":4079},{"style":71},[4080],{"type":25,"value":1682},{"type":20,"tag":64,"props":4082,"children":4083},{"style":161},[4084],{"type":25,"value":1751},{"type":20,"tag":64,"props":4086,"children":4087},{"style":142},[4088],{"type":25,"value":1756},{"type":20,"tag":64,"props":4090,"children":4091},{"style":161},[4092],{"type":25,"value":1761},{"type":20,"tag":64,"props":4094,"children":4095},{"style":93},[4096],{"type":25,"value":169},{"type":20,"tag":64,"props":4098,"children":4099},{"class":66,"line":123},[4100,4105,4109,4113],{"type":20,"tag":64,"props":4101,"children":4102},{"style":71},[4103],{"type":25,"value":4104},"        *",{"type":20,"tag":64,"props":4106,"children":4107},{"style":93},[4108],{"type":25,"value":2972},{"type":20,"tag":64,"props":4110,"children":4111},{"style":71},[4112],{"type":25,"value":1682},{"type":20,"tag":64,"props":4114,"children":4115},{"style":93},[4116],{"type":25,"value":2981},{"type":20,"tag":64,"props":4118,"children":4119},{"class":66,"line":152},[4120,4124,4128,4132],{"type":20,"tag":64,"props":4121,"children":4122},{"style":71},[4123],{"type":25,"value":2506},{"type":20,"tag":64,"props":4125,"children":4126},{"style":93},[4127],{"type":25,"value":2809},{"type":20,"tag":64,"props":4129,"children":4130},{"style":71},[4131],{"type":25,"value":2196},{"type":20,"tag":64,"props":4133,"children":4134},{"style":93},[4135],{"type":25,"value":2312},{"type":20,"tag":64,"props":4137,"children":4138},{"class":66,"line":172},[4139,4144,4148],{"type":20,"tag":64,"props":4140,"children":4141},{"style":93},[4142],{"type":25,"value":4143},"            cp",{"type":20,"tag":64,"props":4145,"children":4146},{"style":71},[4147],{"type":25,"value":1720},{"type":20,"tag":64,"props":4149,"children":4150},{"style":93},[4151],{"type":25,"value":169},{"type":20,"tag":64,"props":4153,"children":4154},{"class":66,"line":218},[4155,4160,4164],{"type":20,"tag":64,"props":4156,"children":4157},{"style":93},[4158],{"type":25,"value":4159},"        reqpt ",{"type":20,"tag":64,"props":4161,"children":4162},{"style":71},[4163],{"type":25,"value":1682},{"type":20,"tag":64,"props":4165,"children":4166},{"style":93},[4167],{"type":25,"value":3037},{"type":20,"tag":64,"props":4169,"children":4170},{"class":66,"line":235},[4171,4175],{"type":20,"tag":64,"props":4172,"children":4173},{"style":71},[4174],{"type":25,"value":158},{"type":20,"tag":64,"props":4176,"children":4177},{"style":93},[4178],{"type":25,"value":3051},{"type":20,"tag":64,"props":4180,"children":4181},{"class":66,"line":276},[4182],{"type":20,"tag":64,"props":4183,"children":4184},{"style":93},[4185],{"type":25,"value":2284},{"type":20,"tag":21,"props":4187,"children":4188},{},[4189],{"type":25,"value":4190},"If the input data contains a comma, this block will execute and return from the function. So to continue on, the input must not contain a comma.",{"type":20,"tag":53,"props":4192,"children":4194},{"className":1596,"code":4193,"language":1598,"meta":8,"style":8},"    if (*cp == '=') {\n        cp++;\n        tp = buf;\n        while (cp \u003C reqend && isspace((int)*cp))\n            cp++;\n",[4195],{"type":20,"tag":60,"props":4196,"children":4197},{"__ignoreMap":8},[4198,4229,4244,4260,4308],{"type":20,"tag":64,"props":4199,"children":4200},{"class":66,"line":67},[4201,4205,4209,4213,4217,4221,4225],{"type":20,"tag":64,"props":4202,"children":4203},{"style":71},[4204],{"type":25,"value":129},{"type":20,"tag":64,"props":4206,"children":4207},{"style":93},[4208],{"type":25,"value":868},{"type":20,"tag":64,"props":4210,"children":4211},{"style":71},[4212],{"type":25,"value":893},{"type":20,"tag":64,"props":4214,"children":4215},{"style":93},[4216],{"type":25,"value":2540},{"type":20,"tag":64,"props":4218,"children":4219},{"style":71},[4220],{"type":25,"value":139},{"type":20,"tag":64,"props":4222,"children":4223},{"style":161},[4224],{"type":25,"value":2630},{"type":20,"tag":64,"props":4226,"children":4227},{"style":93},[4228],{"type":25,"value":1660},{"type":20,"tag":64,"props":4230,"children":4231},{"class":66,"line":114},[4232,4236,4240],{"type":20,"tag":64,"props":4233,"children":4234},{"style":93},[4235],{"type":25,"value":3965},{"type":20,"tag":64,"props":4237,"children":4238},{"style":71},[4239],{"type":25,"value":1720},{"type":20,"tag":64,"props":4241,"children":4242},{"style":93},[4243],{"type":25,"value":169},{"type":20,"tag":64,"props":4245,"children":4246},{"class":66,"line":123},[4247,4252,4256],{"type":20,"tag":64,"props":4248,"children":4249},{"style":93},[4250],{"type":25,"value":4251},"        tp ",{"type":20,"tag":64,"props":4253,"children":4254},{"style":71},[4255],{"type":25,"value":1682},{"type":20,"tag":64,"props":4257,"children":4258},{"style":93},[4259],{"type":25,"value":2981},{"type":20,"tag":64,"props":4261,"children":4262},{"class":66,"line":152},[4263,4268,4272,4276,4280,4284,4288,4292,4296,4300,4304],{"type":20,"tag":64,"props":4264,"children":4265},{"style":71},[4266],{"type":25,"value":4267},"        while",{"type":20,"tag":64,"props":4269,"children":4270},{"style":93},[4271],{"type":25,"value":2809},{"type":20,"tag":64,"props":4273,"children":4274},{"style":71},[4275],{"type":25,"value":2196},{"type":20,"tag":64,"props":4277,"children":4278},{"style":93},[4279],{"type":25,"value":2201},{"type":20,"tag":64,"props":4281,"children":4282},{"style":71},[4283],{"type":25,"value":2206},{"type":20,"tag":64,"props":4285,"children":4286},{"style":87},[4287],{"type":25,"value":2238},{"type":20,"tag":64,"props":4289,"children":4290},{"style":93},[4291],{"type":25,"value":1707},{"type":20,"tag":64,"props":4293,"children":4294},{"style":71},[4295],{"type":25,"value":873},{"type":20,"tag":64,"props":4297,"children":4298},{"style":93},[4299],{"type":25,"value":2251},{"type":20,"tag":64,"props":4301,"children":4302},{"style":71},[4303],{"type":25,"value":893},{"type":20,"tag":64,"props":4305,"children":4306},{"style":93},[4307],{"type":25,"value":2846},{"type":20,"tag":64,"props":4309,"children":4310},{"class":66,"line":172},[4311,4315,4319],{"type":20,"tag":64,"props":4312,"children":4313},{"style":93},[4314],{"type":25,"value":4143},{"type":20,"tag":64,"props":4316,"children":4317},{"style":71},[4318],{"type":25,"value":1720},{"type":20,"tag":64,"props":4320,"children":4321},{"style":93},[4322],{"type":25,"value":169},{"type":20,"tag":21,"props":4324,"children":4325},{},[4326],{"type":25,"value":4327},"So long as the input data contains an equals sign, this block will execute. Finally,",{"type":20,"tag":53,"props":4329,"children":4331},{"className":1596,"code":4330,"language":1598,"meta":8,"style":8},"        while (cp \u003C reqend && *cp != ',')\n            *tp++ = *cp++;\n        if (cp \u003C reqend)\n            cp++;\n        *tp = '\\0';\n        while (isspace((int)(*(tp - 1))))\n            *(--tp) = '\\0';\n",[4332],{"type":20,"tag":60,"props":4333,"children":4334},{"__ignoreMap":8},[4335,4378,4414,4433,4448,4479,4526],{"type":20,"tag":64,"props":4336,"children":4337},{"class":66,"line":67},[4338,4342,4346,4350,4354,4358,4362,4366,4370,4374],{"type":20,"tag":64,"props":4339,"children":4340},{"style":71},[4341],{"type":25,"value":4267},{"type":20,"tag":64,"props":4343,"children":4344},{"style":93},[4345],{"type":25,"value":2809},{"type":20,"tag":64,"props":4347,"children":4348},{"style":71},[4349],{"type":25,"value":2196},{"type":20,"tag":64,"props":4351,"children":4352},{"style":93},[4353],{"type":25,"value":2201},{"type":20,"tag":64,"props":4355,"children":4356},{"style":71},[4357],{"type":25,"value":2206},{"type":20,"tag":64,"props":4359,"children":4360},{"style":71},[4361],{"type":25,"value":1615},{"type":20,"tag":64,"props":4363,"children":4364},{"style":93},[4365],{"type":25,"value":2540},{"type":20,"tag":64,"props":4367,"children":4368},{"style":71},[4369],{"type":25,"value":1746},{"type":20,"tag":64,"props":4371,"children":4372},{"style":161},[4373],{"type":25,"value":2228},{"type":20,"tag":64,"props":4375,"children":4376},{"style":93},[4377],{"type":25,"value":111},{"type":20,"tag":64,"props":4379,"children":4380},{"class":66,"line":114},[4381,4386,4390,4394,4398,4402,4406,4410],{"type":20,"tag":64,"props":4382,"children":4383},{"style":71},[4384],{"type":25,"value":4385},"            *",{"type":20,"tag":64,"props":4387,"children":4388},{"style":93},[4389],{"type":25,"value":1906},{"type":20,"tag":64,"props":4391,"children":4392},{"style":71},[4393],{"type":25,"value":1720},{"type":20,"tag":64,"props":4395,"children":4396},{"style":71},[4397],{"type":25,"value":863},{"type":20,"tag":64,"props":4399,"children":4400},{"style":71},[4401],{"type":25,"value":1615},{"type":20,"tag":64,"props":4403,"children":4404},{"style":93},[4405],{"type":25,"value":1895},{"type":20,"tag":64,"props":4407,"children":4408},{"style":71},[4409],{"type":25,"value":1720},{"type":20,"tag":64,"props":4411,"children":4412},{"style":93},[4413],{"type":25,"value":169},{"type":20,"tag":64,"props":4415,"children":4416},{"class":66,"line":123},[4417,4421,4425,4429],{"type":20,"tag":64,"props":4418,"children":4419},{"style":71},[4420],{"type":25,"value":2506},{"type":20,"tag":64,"props":4422,"children":4423},{"style":93},[4424],{"type":25,"value":2809},{"type":20,"tag":64,"props":4426,"children":4427},{"style":71},[4428],{"type":25,"value":2196},{"type":20,"tag":64,"props":4430,"children":4431},{"style":93},[4432],{"type":25,"value":2312},{"type":20,"tag":64,"props":4434,"children":4435},{"class":66,"line":152},[4436,4440,4444],{"type":20,"tag":64,"props":4437,"children":4438},{"style":93},[4439],{"type":25,"value":4143},{"type":20,"tag":64,"props":4441,"children":4442},{"style":71},[4443],{"type":25,"value":1720},{"type":20,"tag":64,"props":4445,"children":4446},{"style":93},[4447],{"type":25,"value":169},{"type":20,"tag":64,"props":4449,"children":4450},{"class":66,"line":172},[4451,4455,4459,4463,4467,4471,4475],{"type":20,"tag":64,"props":4452,"children":4453},{"style":71},[4454],{"type":25,"value":4104},{"type":20,"tag":64,"props":4456,"children":4457},{"style":93},[4458],{"type":25,"value":2593},{"type":20,"tag":64,"props":4460,"children":4461},{"style":71},[4462],{"type":25,"value":1682},{"type":20,"tag":64,"props":4464,"children":4465},{"style":161},[4466],{"type":25,"value":1751},{"type":20,"tag":64,"props":4468,"children":4469},{"style":142},[4470],{"type":25,"value":1756},{"type":20,"tag":64,"props":4472,"children":4473},{"style":161},[4474],{"type":25,"value":1761},{"type":20,"tag":64,"props":4476,"children":4477},{"style":93},[4478],{"type":25,"value":169},{"type":20,"tag":64,"props":4480,"children":4481},{"class":66,"line":218},[4482,4486,4490,4494,4498,4502,4506,4510,4514,4518,4522],{"type":20,"tag":64,"props":4483,"children":4484},{"style":71},[4485],{"type":25,"value":4267},{"type":20,"tag":64,"props":4487,"children":4488},{"style":93},[4489],{"type":25,"value":868},{"type":20,"tag":64,"props":4491,"children":4492},{"style":87},[4493],{"type":25,"value":3372},{"type":20,"tag":64,"props":4495,"children":4496},{"style":93},[4497],{"type":25,"value":1707},{"type":20,"tag":64,"props":4499,"children":4500},{"style":71},[4501],{"type":25,"value":873},{"type":20,"tag":64,"props":4503,"children":4504},{"style":93},[4505],{"type":25,"value":3385},{"type":20,"tag":64,"props":4507,"children":4508},{"style":71},[4509],{"type":25,"value":893},{"type":20,"tag":64,"props":4511,"children":4512},{"style":93},[4513],{"type":25,"value":3394},{"type":20,"tag":64,"props":4515,"children":4516},{"style":71},[4517],{"type":25,"value":1438},{"type":20,"tag":64,"props":4519,"children":4520},{"style":142},[4521],{"type":25,"value":1443},{"type":20,"tag":64,"props":4523,"children":4524},{"style":93},[4525],{"type":25,"value":3407},{"type":20,"tag":64,"props":4527,"children":4528},{"class":66,"line":235},[4529,4533,4537,4541,4545,4549,4553,4557,4561],{"type":20,"tag":64,"props":4530,"children":4531},{"style":71},[4532],{"type":25,"value":4385},{"type":20,"tag":64,"props":4534,"children":4535},{"style":93},[4536],{"type":25,"value":96},{"type":20,"tag":64,"props":4538,"children":4539},{"style":71},[4540],{"type":25,"value":3424},{"type":20,"tag":64,"props":4542,"children":4543},{"style":93},[4544],{"type":25,"value":3429},{"type":20,"tag":64,"props":4546,"children":4547},{"style":71},[4548],{"type":25,"value":1682},{"type":20,"tag":64,"props":4550,"children":4551},{"style":161},[4552],{"type":25,"value":1751},{"type":20,"tag":64,"props":4554,"children":4555},{"style":142},[4556],{"type":25,"value":1756},{"type":20,"tag":64,"props":4558,"children":4559},{"style":161},[4560],{"type":25,"value":1761},{"type":20,"tag":64,"props":4562,"children":4563},{"style":93},[4564],{"type":25,"value":169},{"type":20,"tag":21,"props":4566,"children":4567},{},[4568,4570,4575,4577,4582,4584,4589,4591,4597,4599,4604],{"type":25,"value":4569},"We've reached the code which copies into ",{"type":20,"tag":60,"props":4571,"children":4573},{"className":4572},[],[4574],{"type":25,"value":1884},{"type":25,"value":4576}," (via ",{"type":20,"tag":60,"props":4578,"children":4580},{"className":4579},[],[4581],{"type":25,"value":1906},{"type":25,"value":4583},"). So long as ",{"type":20,"tag":60,"props":4585,"children":4587},{"className":4586},[],[4588],{"type":25,"value":1895},{"type":25,"value":4590}," is not a comma and is less than the end of the input data (",{"type":20,"tag":60,"props":4592,"children":4594},{"className":4593},[],[4595],{"type":25,"value":4596},"reqend",{"type":25,"value":4598},"), the copy continues. Notably, no checks prevent this loop from executing 128+ times and blowing the stack of ",{"type":20,"tag":60,"props":4600,"children":4602},{"className":4601},[],[4603],{"type":25,"value":1884},{"type":25,"value":4605},", since the input data can exceed that size. Reviewing the preconditions we've built up for reaching this point in the code, we only have",{"type":20,"tag":1035,"props":4607,"children":4608},{},[4609,4614],{"type":20,"tag":1039,"props":4610,"children":4611},{},[4612],{"type":25,"value":4613},"input does not contain a comma, and",{"type":20,"tag":1039,"props":4615,"children":4616},{},[4617],{"type":25,"value":4618},"input contains an equals sign.",{"type":20,"tag":21,"props":4620,"children":4621},{},[4622,4624,4629],{"type":25,"value":4623},"This sounds loose enough to be practically exploitable, and it turns out it was, by writing and executing malicious code on the stack beyond ",{"type":20,"tag":60,"props":4625,"children":4627},{"className":4626},[],[4628],{"type":25,"value":1884},{"type":25,"value":4630},". The lack of bounds checking is obvious once it's singled out, but buried among the other checks and validations, it's much harder to find.",{"type":20,"tag":1023,"props":4632,"children":4634},{"id":4633},"mitigation-in-ntpd",[4635],{"type":25,"value":4636},"Mitigation in NTPD",{"type":20,"tag":21,"props":4638,"children":4639},{},[4640,4642,4647],{"type":25,"value":4641},"The mitigation applied for this vulnerability was as simple as you might expect: adding another condition to the ",{"type":20,"tag":60,"props":4643,"children":4645},{"className":4644},[],[4646],{"type":25,"value":3709},{"type":25,"value":4648}," loop performing the copy:",{"type":20,"tag":53,"props":4650,"children":4652},{"className":1596,"code":4651,"language":1598,"meta":8,"style":8},"        while (cp \u003C reqend && *cp != ',') {\n            *tp++ = *cp++;\n            if (tp >= buf + sizeof(buf) - 1) {\n#if 0  /* don't syslog for now - DoS potential on filling syslog */\n                msyslog(LOG_WARNING,\n                    \"Attempted \\\"ntpdx\\\" exploit from IP %d.%d.%d.%d:%d (possibly spoofed)\\n\",\n                    (ntohl(rmt_addr->sin_addr.s_addr) >> 24) & 0xff,\n                    (ntohl(rmt_addr->sin_addr.s_addr) >> 16) & 0xff,\n                    (ntohl(rmt_addr->sin_addr.s_addr) >> 8) & 0xff,\n                    (ntohl(rmt_addr->sin_addr.s_addr) >> 0) & 0xff,\n                    ntohs(rmt_addr->sin_port));\n#endif\n                return (0);\n            }\n        }\n",[4653],{"type":20,"tag":60,"props":4654,"children":4655},{"__ignoreMap":8},[4656,4699,4734,4781,4798,4806,4814,4822,4830,4838,4846,4854,4862,4882,4889],{"type":20,"tag":64,"props":4657,"children":4658},{"class":66,"line":67},[4659,4663,4667,4671,4675,4679,4683,4687,4691,4695],{"type":20,"tag":64,"props":4660,"children":4661},{"style":71},[4662],{"type":25,"value":4267},{"type":20,"tag":64,"props":4664,"children":4665},{"style":93},[4666],{"type":25,"value":2809},{"type":20,"tag":64,"props":4668,"children":4669},{"style":71},[4670],{"type":25,"value":2196},{"type":20,"tag":64,"props":4672,"children":4673},{"style":93},[4674],{"type":25,"value":2201},{"type":20,"tag":64,"props":4676,"children":4677},{"style":71},[4678],{"type":25,"value":2206},{"type":20,"tag":64,"props":4680,"children":4681},{"style":71},[4682],{"type":25,"value":1615},{"type":20,"tag":64,"props":4684,"children":4685},{"style":93},[4686],{"type":25,"value":2540},{"type":20,"tag":64,"props":4688,"children":4689},{"style":71},[4690],{"type":25,"value":1746},{"type":20,"tag":64,"props":4692,"children":4693},{"style":161},[4694],{"type":25,"value":2228},{"type":20,"tag":64,"props":4696,"children":4697},{"style":93},[4698],{"type":25,"value":1660},{"type":20,"tag":64,"props":4700,"children":4701},{"class":66,"line":114},[4702,4706,4710,4714,4718,4722,4726,4730],{"type":20,"tag":64,"props":4703,"children":4704},{"style":71},[4705],{"type":25,"value":4385},{"type":20,"tag":64,"props":4707,"children":4708},{"style":93},[4709],{"type":25,"value":1906},{"type":20,"tag":64,"props":4711,"children":4712},{"style":71},[4713],{"type":25,"value":1720},{"type":20,"tag":64,"props":4715,"children":4716},{"style":71},[4717],{"type":25,"value":863},{"type":20,"tag":64,"props":4719,"children":4720},{"style":71},[4721],{"type":25,"value":1615},{"type":20,"tag":64,"props":4723,"children":4724},{"style":93},[4725],{"type":25,"value":1895},{"type":20,"tag":64,"props":4727,"children":4728},{"style":71},[4729],{"type":25,"value":1720},{"type":20,"tag":64,"props":4731,"children":4732},{"style":93},[4733],{"type":25,"value":169},{"type":20,"tag":64,"props":4735,"children":4736},{"class":66,"line":123},[4737,4741,4746,4750,4755,4759,4764,4769,4773,4777],{"type":20,"tag":64,"props":4738,"children":4739},{"style":71},[4740],{"type":25,"value":2732},{"type":20,"tag":64,"props":4742,"children":4743},{"style":93},[4744],{"type":25,"value":4745}," (tp ",{"type":20,"tag":64,"props":4747,"children":4748},{"style":71},[4749],{"type":25,"value":2307},{"type":20,"tag":64,"props":4751,"children":4752},{"style":93},[4753],{"type":25,"value":4754}," buf ",{"type":20,"tag":64,"props":4756,"children":4757},{"style":71},[4758],{"type":25,"value":938},{"type":20,"tag":64,"props":4760,"children":4761},{"style":71},[4762],{"type":25,"value":4763}," sizeof",{"type":20,"tag":64,"props":4765,"children":4766},{"style":93},[4767],{"type":25,"value":4768},"(buf) ",{"type":20,"tag":64,"props":4770,"children":4771},{"style":71},[4772],{"type":25,"value":1438},{"type":20,"tag":64,"props":4774,"children":4775},{"style":142},[4776],{"type":25,"value":1443},{"type":20,"tag":64,"props":4778,"children":4779},{"style":93},[4780],{"type":25,"value":1660},{"type":20,"tag":64,"props":4782,"children":4783},{"class":66,"line":152},[4784,4789,4793],{"type":20,"tag":64,"props":4785,"children":4786},{"style":71},[4787],{"type":25,"value":4788},"#if",{"type":20,"tag":64,"props":4790,"children":4791},{"style":142},[4792],{"type":25,"value":145},{"type":20,"tag":64,"props":4794,"children":4795},{"style":2160},[4796],{"type":25,"value":4797},"  /* don't syslog for now - DoS potential on filling syslog */\n",{"type":20,"tag":64,"props":4799,"children":4800},{"class":66,"line":172},[4801],{"type":20,"tag":64,"props":4802,"children":4803},{"style":2160},[4804],{"type":25,"value":4805},"                msyslog(LOG_WARNING,\n",{"type":20,"tag":64,"props":4807,"children":4808},{"class":66,"line":218},[4809],{"type":20,"tag":64,"props":4810,"children":4811},{"style":2160},[4812],{"type":25,"value":4813},"                    \"Attempted \\\"ntpdx\\\" exploit from IP %d.%d.%d.%d:%d (possibly spoofed)\\n\",\n",{"type":20,"tag":64,"props":4815,"children":4816},{"class":66,"line":235},[4817],{"type":20,"tag":64,"props":4818,"children":4819},{"style":2160},[4820],{"type":25,"value":4821},"                    (ntohl(rmt_addr->sin_addr.s_addr) >> 24) & 0xff,\n",{"type":20,"tag":64,"props":4823,"children":4824},{"class":66,"line":276},[4825],{"type":20,"tag":64,"props":4826,"children":4827},{"style":2160},[4828],{"type":25,"value":4829},"                    (ntohl(rmt_addr->sin_addr.s_addr) >> 16) & 0xff,\n",{"type":20,"tag":64,"props":4831,"children":4832},{"class":66,"line":293},[4833],{"type":20,"tag":64,"props":4834,"children":4835},{"style":2160},[4836],{"type":25,"value":4837},"                    (ntohl(rmt_addr->sin_addr.s_addr) >> 8) & 0xff,\n",{"type":20,"tag":64,"props":4839,"children":4840},{"class":66,"line":334},[4841],{"type":20,"tag":64,"props":4842,"children":4843},{"style":2160},[4844],{"type":25,"value":4845},"                    (ntohl(rmt_addr->sin_addr.s_addr) >> 0) & 0xff,\n",{"type":20,"tag":64,"props":4847,"children":4848},{"class":66,"line":351},[4849],{"type":20,"tag":64,"props":4850,"children":4851},{"style":2160},[4852],{"type":25,"value":4853},"                    ntohs(rmt_addr->sin_port));\n",{"type":20,"tag":64,"props":4855,"children":4856},{"class":66,"line":392},[4857],{"type":20,"tag":64,"props":4858,"children":4859},{"style":71},[4860],{"type":25,"value":4861},"#endif\n",{"type":20,"tag":64,"props":4863,"children":4864},{"class":66,"line":409},[4865,4870,4874,4878],{"type":20,"tag":64,"props":4866,"children":4867},{"style":71},[4868],{"type":25,"value":4869},"                return",{"type":20,"tag":64,"props":4871,"children":4872},{"style":93},[4873],{"type":25,"value":868},{"type":20,"tag":64,"props":4875,"children":4876},{"style":142},[4877],{"type":25,"value":2111},{"type":20,"tag":64,"props":4879,"children":4880},{"style":93},[4881],{"type":25,"value":903},{"type":20,"tag":64,"props":4883,"children":4884},{"class":66,"line":450},[4885],{"type":20,"tag":64,"props":4886,"children":4887},{"style":93},[4888],{"type":25,"value":2715},{"type":20,"tag":64,"props":4890,"children":4891},{"class":66,"line":467},[4892],{"type":20,"tag":64,"props":4893,"children":4894},{"style":93},[4895],{"type":25,"value":3547},{"type":20,"tag":21,"props":4897,"children":4898},{},[4899],{"type":25,"value":4900},"It worth appreciating how the potential exploitability of the fix was itself taken into consideration, by choosing not to write logs when the size check is triggered. NTP is a UDP-based protocol which means that source IP addresses can be spoofed by the sender, so it was decided that there wasn't enough value in logging potentially-spoofed IPs given that it potentially introduces a resource exhaustion denial-of-service attack (by deliberately filling up the server's logs).",{"type":20,"tag":1023,"props":4902,"children":4904},{"id":4903},"takeaways",[4905],{"type":25,"value":4906},"Takeaways",{"type":20,"tag":1862,"props":4908,"children":4909},{},[4910,4915,4920],{"type":20,"tag":1039,"props":4911,"children":4912},{},[4913],{"type":25,"value":4914},"Copying untrusted data in memory-unsafe languages is a risky process which must be done  with the utmost care.",{"type":20,"tag":1039,"props":4916,"children":4917},{},[4918],{"type":25,"value":4919},"When code which performs a copy is being a reviewed, a useful technique is to step through each code path leading up to the loop and assess whether any of them could cause the copy to overflow the buffer.",{"type":20,"tag":1039,"props":4921,"children":4922},{},[4923,4925,4931,4933,4939],{"type":25,"value":4924},"Whenever possible, \"safe\" size-aware copying routines should be used (e.g. ",{"type":20,"tag":60,"props":4926,"children":4928},{"className":4927},[],[4929],{"type":25,"value":4930},"strncpy",{"type":25,"value":4932},") in place of \"unsafe\" routines (e.g. ",{"type":20,"tag":60,"props":4934,"children":4936},{"className":4935},[],[4937],{"type":25,"value":4938},"strcpy",{"type":25,"value":4940},") or ad-hoc code.",{"type":20,"tag":1519,"props":4942,"children":4943},{},[4944],{"type":25,"value":1523},{"title":8,"searchDepth":123,"depth":123,"links":4946},[4947,4948,4949,4950,4951],{"id":1572,"depth":114,"text":1575},{"id":1847,"depth":114,"text":1850},{"id":3600,"depth":114,"text":3603},{"id":4633,"depth":114,"text":4636},{"id":4903,"depth":114,"text":4906},"content:phendry:2021-10-30:SpotTheVulnLoopsAndTermConditions.md","phendry/2021-10-30/SpotTheVulnLoopsAndTermConditions.md","phendry/2021-10-30/SpotTheVulnLoopsAndTermConditions",{"user":1536,"name":1537},{"_path":4957,"_dir":4958,"_draft":7,"_partial":7,"_locale":8,"title":4959,"description":4960,"image":4961,"tags":4962,"publishDate":4958,"excerpt":4960,"body":4963,"_type":1529,"_id":5751,"_source":1531,"_file":5752,"_stem":5753,"_extension":1534,"author":5754},"/phendry/2021-07-30/spotthevulndataranges","2021-07-30","Spot the Vulnerability: Data Ranges and Untrusted Input","In 1997, a flaw was discovered in how Linux and Windows handled IP fragmentation, a Denial-of-Service vulnerability which allowed systems to be crashed remotely.","/phendry/2021-07-30/img/vulnerability.jpg",[12,13],{"type":17,"children":4964,"toc":5744},[4965,4969,4975,4980,4985,4991,4996,5006,5011,5404,5452,5456,5466,5504,5539,5589,5594,5603,5615,5650,5656,5675,5688,5692,5740],{"type":20,"tag":21,"props":4966,"children":4967},{},[4968],{"type":25,"value":4960},{"type":20,"tag":1023,"props":4970,"children":4972},{"id":4971},"background-ip-fragmentation",[4973],{"type":25,"value":4974},"Background: IP Fragmentation",{"type":20,"tag":21,"props":4976,"children":4977},{},[4978],{"type":25,"value":4979},"IP Fragmentation occurs when a packet passes through a link whose MTU is smaller than the packet size; it gets fragmented into multiple smaller packets, and subsequently reassembled by the receiver.",{"type":20,"tag":21,"props":4981,"children":4982},{},[4983],{"type":25,"value":4984},"The data in these fragments would typically be non-overlapping, but since partial overlap is permitted by the protocol, IP implementations need to handle that case.",{"type":20,"tag":1023,"props":4986,"children":4988},{"id":4987},"re-assembling-fragmented-packets",[4989],{"type":25,"value":4990},"Re-assembling Fragmented Packets",{"type":20,"tag":21,"props":4992,"children":4993},{},[4994],{"type":25,"value":4995},"When Linux reassembled fragmented packets, it would loop over each fragment, copying the payload of each fragment into a newly-allocated buffer. In order to handle the case where a fragment overlaps with the previous fragment, if its start offset was less than the end offset of the previous fragment, then its start offset would be moved forward to eliminate the overlap. Here's a diagram to help visualize this:",{"type":20,"tag":53,"props":4997,"children":5001},{"className":4998,"code":5000,"language":25},[4999],"language-text","0                    22                40\nv                     v                 v\n|-----Fragment--1-----|\n                  |-----Fragment--2-----|\n                  ^  \\\n                 19   \\\n                       Overlap here\n\nbecomes...\n\n0                    22                40\nv                     v                 v\n|-----Fragment--1-----|\n                      |---Fragment--2---|\n                    \\\n                     \\\n                      Overlap discarded\n",[5002],{"type":20,"tag":60,"props":5003,"children":5004},{"__ignoreMap":8},[5005],{"type":25,"value":5000},{"type":20,"tag":21,"props":5007,"children":5008},{},[5009],{"type":25,"value":5010},"And here's how this was implemented (with only relevant code shown):",{"type":20,"tag":53,"props":5012,"children":5014},{"className":1596,"code":5013,"language":1598,"meta":8,"style":8},"/*\n *      Determine the position of this fragment.\n */\n\nend = offset + ntohs(iph->tot_len) - ihl;\n\n...\n\n/*\n *      We found where to put this one.\n *      Check for overlap with preceding fragment, and, if needed,\n *      align things so that any overlaps are eliminated.\n */\nif (prev != NULL && offset \u003C prev->end)\n{\n        i = prev->end - offset;\n        offset += i;    /* ptr into datagram */\n        ptr += i;       /* ptr into fragment data */\n}\n\n...\n\n/* Fill in the structure. */\nfp->offset = offset;\nfp->end = end;\nfp->len = end - offset;\n",[5015],{"type":20,"tag":60,"props":5016,"children":5017},{"__ignoreMap":8},[5018,5026,5034,5042,5049,5102,5109,5117,5124,5131,5139,5147,5155,5162,5209,5216,5242,5265,5286,5293,5300,5307,5314,5322,5347,5371],{"type":20,"tag":64,"props":5019,"children":5020},{"class":66,"line":67},[5021],{"type":20,"tag":64,"props":5022,"children":5023},{"style":2160},[5024],{"type":25,"value":5025},"/*\n",{"type":20,"tag":64,"props":5027,"children":5028},{"class":66,"line":114},[5029],{"type":20,"tag":64,"props":5030,"children":5031},{"style":2160},[5032],{"type":25,"value":5033}," *      Determine the position of this fragment.\n",{"type":20,"tag":64,"props":5035,"children":5036},{"class":66,"line":123},[5037],{"type":20,"tag":64,"props":5038,"children":5039},{"style":2160},[5040],{"type":25,"value":5041}," */\n",{"type":20,"tag":64,"props":5043,"children":5044},{"class":66,"line":152},[5045],{"type":20,"tag":64,"props":5046,"children":5047},{"emptyLinePlaceholder":703},[5048],{"type":25,"value":706},{"type":20,"tag":64,"props":5050,"children":5051},{"class":66,"line":172},[5052,5057,5061,5066,5070,5075,5080,5084,5089,5093,5097],{"type":20,"tag":64,"props":5053,"children":5054},{"style":93},[5055],{"type":25,"value":5056},"end ",{"type":20,"tag":64,"props":5058,"children":5059},{"style":71},[5060],{"type":25,"value":1682},{"type":20,"tag":64,"props":5062,"children":5063},{"style":93},[5064],{"type":25,"value":5065}," offset ",{"type":20,"tag":64,"props":5067,"children":5068},{"style":71},[5069],{"type":25,"value":938},{"type":20,"tag":64,"props":5071,"children":5072},{"style":87},[5073],{"type":25,"value":5074}," ntohs",{"type":20,"tag":64,"props":5076,"children":5077},{"style":93},[5078],{"type":25,"value":5079},"(iph",{"type":20,"tag":64,"props":5081,"children":5082},{"style":71},[5083],{"type":25,"value":3696},{"type":20,"tag":64,"props":5085,"children":5086},{"style":1635},[5087],{"type":25,"value":5088},"tot_len",{"type":20,"tag":64,"props":5090,"children":5091},{"style":93},[5092],{"type":25,"value":1741},{"type":20,"tag":64,"props":5094,"children":5095},{"style":71},[5096],{"type":25,"value":1438},{"type":20,"tag":64,"props":5098,"children":5099},{"style":93},[5100],{"type":25,"value":5101}," ihl;\n",{"type":20,"tag":64,"props":5103,"children":5104},{"class":66,"line":218},[5105],{"type":20,"tag":64,"props":5106,"children":5107},{"emptyLinePlaceholder":703},[5108],{"type":25,"value":706},{"type":20,"tag":64,"props":5110,"children":5111},{"class":66,"line":235},[5112],{"type":20,"tag":64,"props":5113,"children":5114},{"style":93},[5115],{"type":25,"value":5116},"...\n",{"type":20,"tag":64,"props":5118,"children":5119},{"class":66,"line":276},[5120],{"type":20,"tag":64,"props":5121,"children":5122},{"emptyLinePlaceholder":703},[5123],{"type":25,"value":706},{"type":20,"tag":64,"props":5125,"children":5126},{"class":66,"line":293},[5127],{"type":20,"tag":64,"props":5128,"children":5129},{"style":2160},[5130],{"type":25,"value":5025},{"type":20,"tag":64,"props":5132,"children":5133},{"class":66,"line":334},[5134],{"type":20,"tag":64,"props":5135,"children":5136},{"style":2160},[5137],{"type":25,"value":5138}," *      We found where to put this one.\n",{"type":20,"tag":64,"props":5140,"children":5141},{"class":66,"line":351},[5142],{"type":20,"tag":64,"props":5143,"children":5144},{"style":2160},[5145],{"type":25,"value":5146}," *      Check for overlap with preceding fragment, and, if needed,\n",{"type":20,"tag":64,"props":5148,"children":5149},{"class":66,"line":392},[5150],{"type":20,"tag":64,"props":5151,"children":5152},{"style":2160},[5153],{"type":25,"value":5154}," *      align things so that any overlaps are eliminated.\n",{"type":20,"tag":64,"props":5156,"children":5157},{"class":66,"line":409},[5158],{"type":20,"tag":64,"props":5159,"children":5160},{"style":2160},[5161],{"type":25,"value":5041},{"type":20,"tag":64,"props":5163,"children":5164},{"class":66,"line":450},[5165,5169,5174,5178,5183,5187,5191,5195,5200,5204],{"type":20,"tag":64,"props":5166,"children":5167},{"style":71},[5168],{"type":25,"value":772},{"type":20,"tag":64,"props":5170,"children":5171},{"style":93},[5172],{"type":25,"value":5173}," (prev ",{"type":20,"tag":64,"props":5175,"children":5176},{"style":71},[5177],{"type":25,"value":1746},{"type":20,"tag":64,"props":5179,"children":5180},{"style":142},[5181],{"type":25,"value":5182}," NULL",{"type":20,"tag":64,"props":5184,"children":5185},{"style":71},[5186],{"type":25,"value":196},{"type":20,"tag":64,"props":5188,"children":5189},{"style":93},[5190],{"type":25,"value":5065},{"type":20,"tag":64,"props":5192,"children":5193},{"style":71},[5194],{"type":25,"value":2196},{"type":20,"tag":64,"props":5196,"children":5197},{"style":93},[5198],{"type":25,"value":5199}," prev",{"type":20,"tag":64,"props":5201,"children":5202},{"style":71},[5203],{"type":25,"value":3696},{"type":20,"tag":64,"props":5205,"children":5206},{"style":93},[5207],{"type":25,"value":5208},"end)\n",{"type":20,"tag":64,"props":5210,"children":5211},{"class":66,"line":467},[5212],{"type":20,"tag":64,"props":5213,"children":5214},{"style":93},[5215],{"type":25,"value":120},{"type":20,"tag":64,"props":5217,"children":5218},{"class":66,"line":508},[5219,5224,5228,5233,5237],{"type":20,"tag":64,"props":5220,"children":5221},{"style":93},[5222],{"type":25,"value":5223},"        i ",{"type":20,"tag":64,"props":5225,"children":5226},{"style":71},[5227],{"type":25,"value":1682},{"type":20,"tag":64,"props":5229,"children":5230},{"style":93},[5231],{"type":25,"value":5232}," prev->end ",{"type":20,"tag":64,"props":5234,"children":5235},{"style":71},[5236],{"type":25,"value":1438},{"type":20,"tag":64,"props":5238,"children":5239},{"style":93},[5240],{"type":25,"value":5241}," offset;\n",{"type":20,"tag":64,"props":5243,"children":5244},{"class":66,"line":525},[5245,5250,5255,5260],{"type":20,"tag":64,"props":5246,"children":5247},{"style":93},[5248],{"type":25,"value":5249},"        offset ",{"type":20,"tag":64,"props":5251,"children":5252},{"style":71},[5253],{"type":25,"value":5254},"+=",{"type":20,"tag":64,"props":5256,"children":5257},{"style":93},[5258],{"type":25,"value":5259}," i;",{"type":20,"tag":64,"props":5261,"children":5262},{"style":2160},[5263],{"type":25,"value":5264},"    /* ptr into datagram */\n",{"type":20,"tag":64,"props":5266,"children":5267},{"class":66,"line":566},[5268,5273,5277,5281],{"type":20,"tag":64,"props":5269,"children":5270},{"style":93},[5271],{"type":25,"value":5272},"        ptr ",{"type":20,"tag":64,"props":5274,"children":5275},{"style":71},[5276],{"type":25,"value":5254},{"type":20,"tag":64,"props":5278,"children":5279},{"style":93},[5280],{"type":25,"value":5259},{"type":20,"tag":64,"props":5282,"children":5283},{"style":2160},[5284],{"type":25,"value":5285},"       /* ptr into fragment data */\n",{"type":20,"tag":64,"props":5287,"children":5288},{"class":66,"line":583},[5289],{"type":20,"tag":64,"props":5290,"children":5291},{"style":93},[5292],{"type":25,"value":733},{"type":20,"tag":64,"props":5294,"children":5295},{"class":66,"line":624},[5296],{"type":20,"tag":64,"props":5297,"children":5298},{"emptyLinePlaceholder":703},[5299],{"type":25,"value":706},{"type":20,"tag":64,"props":5301,"children":5302},{"class":66,"line":641},[5303],{"type":20,"tag":64,"props":5304,"children":5305},{"style":93},[5306],{"type":25,"value":5116},{"type":20,"tag":64,"props":5308,"children":5309},{"class":66,"line":682},[5310],{"type":20,"tag":64,"props":5311,"children":5312},{"emptyLinePlaceholder":703},[5313],{"type":25,"value":706},{"type":20,"tag":64,"props":5315,"children":5316},{"class":66,"line":699},[5317],{"type":20,"tag":64,"props":5318,"children":5319},{"style":2160},[5320],{"type":25,"value":5321},"/* Fill in the structure. */\n",{"type":20,"tag":64,"props":5323,"children":5324},{"class":66,"line":709},[5325,5330,5334,5339,5343],{"type":20,"tag":64,"props":5326,"children":5327},{"style":93},[5328],{"type":25,"value":5329},"fp",{"type":20,"tag":64,"props":5331,"children":5332},{"style":71},[5333],{"type":25,"value":3696},{"type":20,"tag":64,"props":5335,"children":5336},{"style":93},[5337],{"type":25,"value":5338},"offset ",{"type":20,"tag":64,"props":5340,"children":5341},{"style":71},[5342],{"type":25,"value":1682},{"type":20,"tag":64,"props":5344,"children":5345},{"style":93},[5346],{"type":25,"value":5241},{"type":20,"tag":64,"props":5348,"children":5349},{"class":66,"line":727},[5350,5354,5358,5362,5366],{"type":20,"tag":64,"props":5351,"children":5352},{"style":93},[5353],{"type":25,"value":5329},{"type":20,"tag":64,"props":5355,"children":5356},{"style":71},[5357],{"type":25,"value":3696},{"type":20,"tag":64,"props":5359,"children":5360},{"style":93},[5361],{"type":25,"value":5056},{"type":20,"tag":64,"props":5363,"children":5364},{"style":71},[5365],{"type":25,"value":1682},{"type":20,"tag":64,"props":5367,"children":5368},{"style":93},[5369],{"type":25,"value":5370}," end;\n",{"type":20,"tag":64,"props":5372,"children":5373},{"class":66,"line":2407},[5374,5378,5382,5387,5391,5396,5400],{"type":20,"tag":64,"props":5375,"children":5376},{"style":93},[5377],{"type":25,"value":5329},{"type":20,"tag":64,"props":5379,"children":5380},{"style":71},[5381],{"type":25,"value":3696},{"type":20,"tag":64,"props":5383,"children":5384},{"style":93},[5385],{"type":25,"value":5386},"len ",{"type":20,"tag":64,"props":5388,"children":5389},{"style":71},[5390],{"type":25,"value":1682},{"type":20,"tag":64,"props":5392,"children":5393},{"style":93},[5394],{"type":25,"value":5395}," end ",{"type":20,"tag":64,"props":5397,"children":5398},{"style":71},[5399],{"type":25,"value":1438},{"type":20,"tag":64,"props":5401,"children":5402},{"style":93},[5403],{"type":25,"value":5241},{"type":20,"tag":21,"props":5405,"children":5406},{},[5407,5413,5415,5420,5422,5427,5429,5435,5437,5442,5444,5450],{"type":20,"tag":60,"props":5408,"children":5410},{"className":5409},[],[5411],{"type":25,"value":5412},"offset",{"type":25,"value":5414}," is the fragment's offset in the complete datagram. So if ",{"type":20,"tag":60,"props":5416,"children":5418},{"className":5417},[],[5419],{"type":25,"value":5412},{"type":25,"value":5421}," is before the end of the previous fragment, then the middle ",{"type":20,"tag":60,"props":5423,"children":5425},{"className":5424},[],[5426],{"type":25,"value":772},{"type":25,"value":5428}," block above sets it to the value of ",{"type":20,"tag":60,"props":5430,"children":5432},{"className":5431},[],[5433],{"type":25,"value":5434},"prev->end",{"type":25,"value":5436},", eliminating the overlap. Finally, length of the fragment is updated based on the new ",{"type":20,"tag":60,"props":5438,"children":5440},{"className":5439},[],[5441],{"type":25,"value":5412},{"type":25,"value":5443}," and ",{"type":20,"tag":60,"props":5445,"children":5447},{"className":5446},[],[5448],{"type":25,"value":5449},"end",{"type":25,"value":5451}," of the fragment.",{"type":20,"tag":1023,"props":5453,"children":5454},{"id":3600},[5455],{"type":25,"value":3603},{"type":20,"tag":21,"props":5457,"children":5458},{},[5459,5461],{"type":25,"value":5460},"Whenever we're using arithmetic to compute a size or length, we need to ask ourselves: ",{"type":20,"tag":776,"props":5462,"children":5463},{},[5464],{"type":25,"value":5465},"can this turn out negative?",{"type":20,"tag":53,"props":5467,"children":5469},{"className":1596,"code":5468,"language":1598,"meta":8,"style":8},"fp->len = end - offset;\n",[5470],{"type":20,"tag":60,"props":5471,"children":5472},{"__ignoreMap":8},[5473],{"type":20,"tag":64,"props":5474,"children":5475},{"class":66,"line":67},[5476,5480,5484,5488,5492,5496,5500],{"type":20,"tag":64,"props":5477,"children":5478},{"style":93},[5479],{"type":25,"value":5329},{"type":20,"tag":64,"props":5481,"children":5482},{"style":71},[5483],{"type":25,"value":3696},{"type":20,"tag":64,"props":5485,"children":5486},{"style":93},[5487],{"type":25,"value":5386},{"type":20,"tag":64,"props":5489,"children":5490},{"style":71},[5491],{"type":25,"value":1682},{"type":20,"tag":64,"props":5493,"children":5494},{"style":93},[5495],{"type":25,"value":5395},{"type":20,"tag":64,"props":5497,"children":5498},{"style":71},[5499],{"type":25,"value":1438},{"type":20,"tag":64,"props":5501,"children":5502},{"style":93},[5503],{"type":25,"value":5241},{"type":20,"tag":21,"props":5505,"children":5506},{},[5507,5509,5514,5516,5522,5524,5529,5531,5537],{"type":25,"value":5508},"At first glance, it seems like the answer is \"no\" for this fragment: ",{"type":20,"tag":60,"props":5510,"children":5512},{"className":5511},[],[5513],{"type":25,"value":5449},{"type":25,"value":5515}," is defined by adding the fragment's payload length (definitely ",{"type":20,"tag":60,"props":5517,"children":5519},{"className":5518},[],[5520],{"type":25,"value":5521},">= 0",{"type":25,"value":5523},") to the value of ",{"type":20,"tag":60,"props":5525,"children":5527},{"className":5526},[],[5528],{"type":25,"value":5412},{"type":25,"value":5530},", so it would seem that ",{"type":20,"tag":60,"props":5532,"children":5534},{"className":5533},[],[5535],{"type":25,"value":5536},"end - offset >= 0",{"type":25,"value":5538}," must be true.",{"type":20,"tag":21,"props":5540,"children":5541},{},[5542,5544,5549,5551,5557,5559,5564,5566,5571,5573,5579,5581,5587],{"type":25,"value":5543},"However, this analysis ignores what might have happened in between the assignment of ",{"type":20,"tag":60,"props":5545,"children":5547},{"className":5546},[],[5548],{"type":25,"value":5449},{"type":25,"value":5550}," and the evaluation of ",{"type":20,"tag":60,"props":5552,"children":5554},{"className":5553},[],[5555],{"type":25,"value":5556},"end - offset",{"type":25,"value":5558},"; in particular, the handling of overlap. ",{"type":20,"tag":60,"props":5560,"children":5562},{"className":5561},[],[5563],{"type":25,"value":5412},{"type":25,"value":5565}," effectively gets set to ",{"type":20,"tag":60,"props":5567,"children":5569},{"className":5568},[],[5570],{"type":25,"value":5434},{"type":25,"value":5572}," (the end of the previous fragment), but still, this fragment should at worst be a duplicate of the previous one, meaning ",{"type":20,"tag":60,"props":5574,"children":5576},{"className":5575},[],[5577],{"type":25,"value":5578},"prev->end == end",{"type":25,"value":5580},", and consequently ",{"type":20,"tag":60,"props":5582,"children":5584},{"className":5583},[],[5585],{"type":25,"value":5586},"end - offset == 0",{"type":25,"value":5588},". So after a second look, this might still look problem-free.",{"type":20,"tag":21,"props":5590,"children":5591},{},[5592],{"type":25,"value":5593},"The dangerous word here is \"should\". Suppose a pair of fragments comes in that look more like this:",{"type":20,"tag":53,"props":5595,"children":5598},{"className":5596,"code":5597,"language":25},[4999],"0                    22\nv                     v\n|-----Fragment--1-----|\n    |--Fragment--2--|\n    ^               ^\n    4              20\n",[5599],{"type":20,"tag":60,"props":5600,"children":5601},{"__ignoreMap":8},[5602],{"type":25,"value":5597},{"type":20,"tag":21,"props":5604,"children":5605},{},[5606,5608,5613],{"type":25,"value":5607},"This is obviously wrong and shouldn't happen; fragments might overlap or duplicate on another, but they should never be a strict subset of another fragment. Maybe so, but ",{"type":20,"tag":776,"props":5609,"children":5610},{},[5611],{"type":25,"value":5612},"can they, anyway?",{"type":25,"value":5614}," It turns out the answer is yes, they can, for example if they're deliberately crafted that way by a malicious sender.",{"type":20,"tag":21,"props":5616,"children":5617},{},[5618,5620,5625,5627,5632,5634,5640,5642,5648],{"type":25,"value":5619},"If the length of the second fragment is not enough to \"cover\" the overlap correction, then the updated ",{"type":20,"tag":60,"props":5621,"children":5623},{"className":5622},[],[5624],{"type":25,"value":5412},{"type":25,"value":5626}," of the fragment becomes greater than its ",{"type":20,"tag":60,"props":5628,"children":5630},{"className":5629},[],[5631],{"type":25,"value":5449},{"type":25,"value":5633},", and consequently the computed ",{"type":20,"tag":60,"props":5635,"children":5637},{"className":5636},[],[5638],{"type":25,"value":5639},"fp->len",{"type":25,"value":5641}," is negative. This length eventually gets passed to ",{"type":20,"tag":60,"props":5643,"children":5645},{"className":5644},[],[5646],{"type":25,"value":5647},"memcpy()",{"type":25,"value":5649},", causing a buffer overflow and an extremely large copy that will lock up or crash the system.",{"type":20,"tag":1023,"props":5651,"children":5653},{"id":5652},"what-went-wrong",[5654],{"type":25,"value":5655},"What Went Wrong?",{"type":20,"tag":21,"props":5657,"children":5658},{},[5659,5661,5666,5668,5673],{"type":25,"value":5660},"The root cause here was arguably a misplaced trust in untrusted input; it's a very easy mistake to make as a developer, since we naturally expect that all parts of a system ",{"type":20,"tag":776,"props":5662,"children":5663},{},[5664],{"type":25,"value":5665},"want",{"type":25,"value":5667}," to work correctly (even the parts that we don't control). In this case, input is coming from a completely untrusted source, and while there's a whole class of inputs which a robust sender should never send, there's nothing which ",{"type":20,"tag":776,"props":5669,"children":5670},{},[5671],{"type":25,"value":5672},"prevents",{"type":25,"value":5674}," a sender from doing so.",{"type":20,"tag":21,"props":5676,"children":5677},{},[5678,5680,5686],{"type":25,"value":5679},"Given that the input can contain a fragment which is a strict subset of the previous fragment, the implementation needs to guard against this possibility, for example with a ",{"type":20,"tag":60,"props":5681,"children":5683},{"className":5682},[],[5684],{"type":25,"value":5685},"if (offset > end)",{"type":25,"value":5687}," check.",{"type":20,"tag":1023,"props":5689,"children":5690},{"id":4903},[5691],{"type":25,"value":4906},{"type":20,"tag":1862,"props":5693,"children":5694},{},[5695,5707,5712],{"type":20,"tag":1039,"props":5696,"children":5697},{},[5698,5700,5705],{"type":25,"value":5699},"Whenever untrusted data is being processed, it should be treated with the mindset of an attacker: consider not only the expected format of the input, but rather ",{"type":20,"tag":776,"props":5701,"children":5702},{},[5703],{"type":25,"value":5704},"all",{"type":25,"value":5706}," possible formats in could take.",{"type":20,"tag":1039,"props":5708,"children":5709},{},[5710],{"type":25,"value":5711},"Whenever a length or size is being computed, particularly in a memory-unsafe language like C, verify that it's not possible for the value to be negative or otherwise invalid.",{"type":20,"tag":1039,"props":5713,"children":5714},{},[5715,5717],{"type":25,"value":5716},"When working with data ranges, carefully consider the edge cases, such as:\n",{"type":20,"tag":1862,"props":5718,"children":5719},{},[5720,5725,5730,5735],{"type":20,"tag":1039,"props":5721,"children":5722},{},[5723],{"type":25,"value":5724},"Are the ranges always ordered by their start index?",{"type":20,"tag":1039,"props":5726,"children":5727},{},[5728],{"type":25,"value":5729},"Can zero-length ranges exist?",{"type":20,"tag":1039,"props":5731,"children":5732},{},[5733],{"type":25,"value":5734},"Must the ranges be contiguous? (Can gaps exist between them?)",{"type":20,"tag":1039,"props":5736,"children":5737},{},[5738],{"type":25,"value":5739},"Can the ranges overlap? If so, are all types of overlap handled? (Adjacent, partial overlap, duplicate, strict subset)",{"type":20,"tag":1519,"props":5741,"children":5742},{},[5743],{"type":25,"value":1523},{"title":8,"searchDepth":123,"depth":123,"links":5745},[5746,5747,5748,5749,5750],{"id":4971,"depth":114,"text":4974},{"id":4987,"depth":114,"text":4990},{"id":3600,"depth":114,"text":3603},{"id":5652,"depth":114,"text":5655},{"id":4903,"depth":114,"text":4906},"content:phendry:2021-07-30:SpotTheVulnDataRanges.md","phendry/2021-07-30/SpotTheVulnDataRanges.md","phendry/2021-07-30/SpotTheVulnDataRanges",{"user":1536,"name":1537},{"_path":5756,"_dir":5757,"_draft":7,"_partial":7,"_locale":8,"title":5758,"description":5759,"publishDate":5760,"tags":5761,"image":5766,"excerpt":5759,"body":5767,"_type":1529,"_id":7968,"_source":1531,"_file":7969,"_stem":7970,"_extension":1534,"author":7971},"/nharrison/2012-07/core-data","2012-07","Securing Your Core Data with Transformable Attributes","In order to store private data in an iOS Core Data database, there are several methods available for encryption, including:","2012-07-30",[5762,5763,5764,12,5765],"core-data","encryption","ios","objective-c","/nharrison/2012-07/img/superman.jpg",{"type":17,"children":5768,"toc":7956},[5769,5773,5802,5807,5813,5836,5854,5873,5880,5994,6000,6691,6702,6707,6712,6747,6753,7204,7236,7247,7260,7265,7271,7303,7341,7367,7397,7402,7411,7416,7422,7942,7947,7952],{"type":20,"tag":21,"props":5770,"children":5771},{},[5772],{"type":25,"value":5759},{"type":20,"tag":1862,"props":5774,"children":5775},{},[5776,5788],{"type":20,"tag":1039,"props":5777,"children":5778},{},[5779,5786],{"type":20,"tag":28,"props":5780,"children":5783},{"href":5781,"rel":5782},"http://support.apple.com/kb/HT4175",[32],[5784],{"type":25,"value":5785},"iOS-level data protection",{"type":25,"value":5787}," based on the device passcode",{"type":20,"tag":1039,"props":5789,"children":5790},{},[5791,5793,5800],{"type":25,"value":5792},"open source projects like ",{"type":20,"tag":28,"props":5794,"children":5797},{"href":5795,"rel":5796},"http://sqlcipher.net/ios-tutorial/",[32],[5798],{"type":25,"value":5799},"SQLCipher for iOS",{"type":25,"value":5801}," that encrypt the database file",{"type":20,"tag":21,"props":5803,"children":5804},{},[5805],{"type":25,"value":5806},"However, neither of these options is sufficient for if you need to use multiple encryption keys, encrypt only certain attributes, or preserve decrypted data while the device is locked.",{"type":20,"tag":1023,"props":5808,"children":5810},{"id":5809},"encryption-transformer-class",[5811],{"type":25,"value":5812},"Encryption Transformer Class",{"type":20,"tag":21,"props":5814,"children":5815},{},[5816,5818,5825,5827,5834],{"type":25,"value":5817},"Instead, it's fairly simple and straight-forward to perform lazy decryption on only certain database fields using the special ",{"type":20,"tag":28,"props":5819,"children":5822},{"href":5820,"rel":5821},"https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/CoreData/Articles/cdNSAttributes.html",[32],[5823],{"type":25,"value":5824},"Transformable Core Data attribute type",{"type":25,"value":5826},". Transformable attributes are configured with an ",{"type":20,"tag":28,"props":5828,"children":5831},{"href":5829,"rel":5830},"http://developer.apple.com/library/ios/#DOCUMENTATION/Cocoa/Reference/Foundation/Classes/NSValueTransformer_Class/Reference/Reference.html",[32],[5832],{"type":25,"value":5833},"NSValueTransformer",{"type":25,"value":5835}," subclass that you write that specifies:",{"type":20,"tag":1862,"props":5837,"children":5838},{},[5839,5844,5849],{"type":20,"tag":1039,"props":5840,"children":5841},{},[5842],{"type":25,"value":5843},"a method for converting one object into another",{"type":20,"tag":1039,"props":5845,"children":5846},{},[5847],{"type":25,"value":5848},"an optional method for reversing that process (and whether reversing is supported)",{"type":20,"tag":1039,"props":5850,"children":5851},{},[5852],{"type":25,"value":5853},"the class of an object after transformation",{"type":20,"tag":21,"props":5855,"children":5856},{},[5857,5859,5864,5866,5871],{"type":25,"value":5858},"Here's an example class that converts from a decrypted NSData object to an encrypted one. It relies on a ",{"type":20,"tag":1045,"props":5860,"children":5861},{},[5862],{"type":25,"value":5863},"key",{"type":25,"value":5865}," method to get the encryption key, and a couple ",{"type":20,"tag":1045,"props":5867,"children":5868},{},[5869],{"type":25,"value":5870},"NSData",{"type":25,"value":5872}," category methods that perform AES-256 encryption and decryption.",{"type":20,"tag":5874,"props":5875,"children":5877},"h3",{"id":5876},"encryptiontransformerh",[5878],{"type":25,"value":5879},"EncryptionTransformer.h",{"type":20,"tag":53,"props":5881,"children":5885},{"className":5882,"code":5883,"language":5884,"meta":8,"style":8},"language-objc shiki shiki-themes github-light github-dark","@interface EncryptionTransformer : NSValueTransformer\n{}\n\n/**\n * Returns the key used for encrypting / decrypting values during transformation.\n */\n- (NSString*)key;\n\n@end\n","objc",[5886],{"type":20,"tag":60,"props":5887,"children":5888},{"__ignoreMap":8},[5889,5912,5920,5927,5935,5943,5950,5979,5986],{"type":20,"tag":64,"props":5890,"children":5891},{"class":66,"line":67},[5892,5897,5902,5907],{"type":20,"tag":64,"props":5893,"children":5894},{"style":71},[5895],{"type":25,"value":5896},"@interface",{"type":20,"tag":64,"props":5898,"children":5899},{"style":87},[5900],{"type":25,"value":5901}," EncryptionTransformer",{"type":20,"tag":64,"props":5903,"children":5904},{"style":93},[5905],{"type":25,"value":5906}," : ",{"type":20,"tag":64,"props":5908,"children":5909},{"style":87},[5910],{"type":25,"value":5911},"NSValueTransformer\n",{"type":20,"tag":64,"props":5913,"children":5914},{"class":66,"line":114},[5915],{"type":20,"tag":64,"props":5916,"children":5917},{"style":93},[5918],{"type":25,"value":5919},"{}\n",{"type":20,"tag":64,"props":5921,"children":5922},{"class":66,"line":123},[5923],{"type":20,"tag":64,"props":5924,"children":5925},{"emptyLinePlaceholder":703},[5926],{"type":25,"value":706},{"type":20,"tag":64,"props":5928,"children":5929},{"class":66,"line":152},[5930],{"type":20,"tag":64,"props":5931,"children":5932},{"style":2160},[5933],{"type":25,"value":5934},"/**\n",{"type":20,"tag":64,"props":5936,"children":5937},{"class":66,"line":172},[5938],{"type":20,"tag":64,"props":5939,"children":5940},{"style":2160},[5941],{"type":25,"value":5942}," * Returns the key used for encrypting / decrypting values during transformation.\n",{"type":20,"tag":64,"props":5944,"children":5945},{"class":66,"line":218},[5946],{"type":20,"tag":64,"props":5947,"children":5948},{"style":2160},[5949],{"type":25,"value":5041},{"type":20,"tag":64,"props":5951,"children":5952},{"class":66,"line":235},[5953,5958,5963,5967,5971,5975],{"type":20,"tag":64,"props":5954,"children":5955},{"style":93},[5956],{"type":25,"value":5957},"- (",{"type":20,"tag":64,"props":5959,"children":5960},{"style":142},[5961],{"type":25,"value":5962},"NSString",{"type":20,"tag":64,"props":5964,"children":5965},{"style":71},[5966],{"type":25,"value":893},{"type":20,"tag":64,"props":5968,"children":5969},{"style":93},[5970],{"type":25,"value":2251},{"type":20,"tag":64,"props":5972,"children":5973},{"style":87},[5974],{"type":25,"value":5863},{"type":20,"tag":64,"props":5976,"children":5977},{"style":93},[5978],{"type":25,"value":169},{"type":20,"tag":64,"props":5980,"children":5981},{"class":66,"line":276},[5982],{"type":20,"tag":64,"props":5983,"children":5984},{"emptyLinePlaceholder":703},[5985],{"type":25,"value":706},{"type":20,"tag":64,"props":5987,"children":5988},{"class":66,"line":293},[5989],{"type":20,"tag":64,"props":5990,"children":5991},{"style":71},[5992],{"type":25,"value":5993},"@end\n",{"type":20,"tag":5874,"props":5995,"children":5997},{"id":5996},"encryptiontransformerm",[5998],{"type":25,"value":5999},"EncryptionTransformer.m",{"type":20,"tag":53,"props":6001,"children":6003},{"className":5882,"code":6002,"language":5884,"meta":8,"style":8},"@implementation EncryptionTransformer\n\n+ (Class)transformedValueClass\n{\n   return [NSData class];\n}\n\n+ (BOOL)allowsReverseTransformation\n{\n   return YES;\n}\n\n- (NSString*)key\n{\n   // Your version of this class might get this key from the app delegate or elsewhere.\n   return @\"secret key\";\n}\n\n- (id)transformedValue:(NSData*)data\n{\n   // If there's no key (e.g. during a data migration), don't try to transform the data\n   if (nil == [self key])\n   {\n      return data;\n   }\n\n   if (nil == data)\n   {\n      return nil;\n   }\n\n   return [data dataAES256EncryptedWithKey:[self key]];\n}\n\n- (id)reverseTransformedValue:(NSData*)data\n{\n   // If there's no key (e.g. during a data migration), don't try to transform the data\n   if (nil == [self key])\n   {\n      return data;\n   }\n\n   if (nil == data)\n   {\n      return nil;\n   }\n\n   return [data dataAES256DecryptedWithKey:[self key]];\n}\n\n@end\n",[6004],{"type":20,"tag":60,"props":6005,"children":6006},{"__ignoreMap":8},[6007,6020,6027,6049,6056,6082,6089,6096,6117,6124,6140,6147,6154,6178,6185,6193,6209,6216,6223,6261,6268,6276,6317,6325,6338,6346,6353,6377,6384,6400,6407,6414,6448,6455,6462,6498,6505,6512,6547,6554,6565,6572,6579,6602,6609,6624,6631,6638,6670,6677,6684],{"type":20,"tag":64,"props":6008,"children":6009},{"class":66,"line":67},[6010,6015],{"type":20,"tag":64,"props":6011,"children":6012},{"style":71},[6013],{"type":25,"value":6014},"@implementation",{"type":20,"tag":64,"props":6016,"children":6017},{"style":87},[6018],{"type":25,"value":6019}," EncryptionTransformer\n",{"type":20,"tag":64,"props":6021,"children":6022},{"class":66,"line":114},[6023],{"type":20,"tag":64,"props":6024,"children":6025},{"emptyLinePlaceholder":703},[6026],{"type":25,"value":706},{"type":20,"tag":64,"props":6028,"children":6029},{"class":66,"line":123},[6030,6035,6040,6044],{"type":20,"tag":64,"props":6031,"children":6032},{"style":93},[6033],{"type":25,"value":6034},"+ (",{"type":20,"tag":64,"props":6036,"children":6037},{"style":71},[6038],{"type":25,"value":6039},"Class",{"type":20,"tag":64,"props":6041,"children":6042},{"style":93},[6043],{"type":25,"value":2251},{"type":20,"tag":64,"props":6045,"children":6046},{"style":87},[6047],{"type":25,"value":6048},"transformedValueClass\n",{"type":20,"tag":64,"props":6050,"children":6051},{"class":66,"line":152},[6052],{"type":20,"tag":64,"props":6053,"children":6054},{"style":93},[6055],{"type":25,"value":120},{"type":20,"tag":64,"props":6057,"children":6058},{"class":66,"line":172},[6059,6064,6069,6073,6078],{"type":20,"tag":64,"props":6060,"children":6061},{"style":71},[6062],{"type":25,"value":6063},"   return",{"type":20,"tag":64,"props":6065,"children":6066},{"style":93},[6067],{"type":25,"value":6068}," [",{"type":20,"tag":64,"props":6070,"children":6071},{"style":142},[6072],{"type":25,"value":5870},{"type":20,"tag":64,"props":6074,"children":6075},{"style":142},[6076],{"type":25,"value":6077}," class",{"type":20,"tag":64,"props":6079,"children":6080},{"style":93},[6081],{"type":25,"value":2147},{"type":20,"tag":64,"props":6083,"children":6084},{"class":66,"line":218},[6085],{"type":20,"tag":64,"props":6086,"children":6087},{"style":93},[6088],{"type":25,"value":733},{"type":20,"tag":64,"props":6090,"children":6091},{"class":66,"line":235},[6092],{"type":20,"tag":64,"props":6093,"children":6094},{"emptyLinePlaceholder":703},[6095],{"type":25,"value":706},{"type":20,"tag":64,"props":6097,"children":6098},{"class":66,"line":276},[6099,6103,6108,6112],{"type":20,"tag":64,"props":6100,"children":6101},{"style":93},[6102],{"type":25,"value":6034},{"type":20,"tag":64,"props":6104,"children":6105},{"style":71},[6106],{"type":25,"value":6107},"BOOL",{"type":20,"tag":64,"props":6109,"children":6110},{"style":93},[6111],{"type":25,"value":2251},{"type":20,"tag":64,"props":6113,"children":6114},{"style":87},[6115],{"type":25,"value":6116},"allowsReverseTransformation\n",{"type":20,"tag":64,"props":6118,"children":6119},{"class":66,"line":293},[6120],{"type":20,"tag":64,"props":6121,"children":6122},{"style":93},[6123],{"type":25,"value":120},{"type":20,"tag":64,"props":6125,"children":6126},{"class":66,"line":334},[6127,6131,6136],{"type":20,"tag":64,"props":6128,"children":6129},{"style":71},[6130],{"type":25,"value":6063},{"type":20,"tag":64,"props":6132,"children":6133},{"style":142},[6134],{"type":25,"value":6135}," YES",{"type":20,"tag":64,"props":6137,"children":6138},{"style":93},[6139],{"type":25,"value":169},{"type":20,"tag":64,"props":6141,"children":6142},{"class":66,"line":351},[6143],{"type":20,"tag":64,"props":6144,"children":6145},{"style":93},[6146],{"type":25,"value":733},{"type":20,"tag":64,"props":6148,"children":6149},{"class":66,"line":392},[6150],{"type":20,"tag":64,"props":6151,"children":6152},{"emptyLinePlaceholder":703},[6153],{"type":25,"value":706},{"type":20,"tag":64,"props":6155,"children":6156},{"class":66,"line":409},[6157,6161,6165,6169,6173],{"type":20,"tag":64,"props":6158,"children":6159},{"style":93},[6160],{"type":25,"value":5957},{"type":20,"tag":64,"props":6162,"children":6163},{"style":142},[6164],{"type":25,"value":5962},{"type":20,"tag":64,"props":6166,"children":6167},{"style":71},[6168],{"type":25,"value":893},{"type":20,"tag":64,"props":6170,"children":6171},{"style":93},[6172],{"type":25,"value":2251},{"type":20,"tag":64,"props":6174,"children":6175},{"style":87},[6176],{"type":25,"value":6177},"key\n",{"type":20,"tag":64,"props":6179,"children":6180},{"class":66,"line":450},[6181],{"type":20,"tag":64,"props":6182,"children":6183},{"style":93},[6184],{"type":25,"value":120},{"type":20,"tag":64,"props":6186,"children":6187},{"class":66,"line":467},[6188],{"type":20,"tag":64,"props":6189,"children":6190},{"style":2160},[6191],{"type":25,"value":6192},"   // Your version of this class might get this key from the app delegate or elsewhere.\n",{"type":20,"tag":64,"props":6194,"children":6195},{"class":66,"line":508},[6196,6200,6205],{"type":20,"tag":64,"props":6197,"children":6198},{"style":71},[6199],{"type":25,"value":6063},{"type":20,"tag":64,"props":6201,"children":6202},{"style":161},[6203],{"type":25,"value":6204}," @\"secret key\"",{"type":20,"tag":64,"props":6206,"children":6207},{"style":93},[6208],{"type":25,"value":169},{"type":20,"tag":64,"props":6210,"children":6211},{"class":66,"line":525},[6212],{"type":20,"tag":64,"props":6213,"children":6214},{"style":93},[6215],{"type":25,"value":733},{"type":20,"tag":64,"props":6217,"children":6218},{"class":66,"line":566},[6219],{"type":20,"tag":64,"props":6220,"children":6221},{"emptyLinePlaceholder":703},[6222],{"type":25,"value":706},{"type":20,"tag":64,"props":6224,"children":6225},{"class":66,"line":583},[6226,6230,6235,6239,6244,6248,6252,6256],{"type":20,"tag":64,"props":6227,"children":6228},{"style":93},[6229],{"type":25,"value":5957},{"type":20,"tag":64,"props":6231,"children":6232},{"style":71},[6233],{"type":25,"value":6234},"id",{"type":20,"tag":64,"props":6236,"children":6237},{"style":93},[6238],{"type":25,"value":2251},{"type":20,"tag":64,"props":6240,"children":6241},{"style":87},[6242],{"type":25,"value":6243},"transformedValue:",{"type":20,"tag":64,"props":6245,"children":6246},{"style":93},[6247],{"type":25,"value":96},{"type":20,"tag":64,"props":6249,"children":6250},{"style":142},[6251],{"type":25,"value":5870},{"type":20,"tag":64,"props":6253,"children":6254},{"style":71},[6255],{"type":25,"value":893},{"type":20,"tag":64,"props":6257,"children":6258},{"style":93},[6259],{"type":25,"value":6260},")data\n",{"type":20,"tag":64,"props":6262,"children":6263},{"class":66,"line":624},[6264],{"type":20,"tag":64,"props":6265,"children":6266},{"style":93},[6267],{"type":25,"value":120},{"type":20,"tag":64,"props":6269,"children":6270},{"class":66,"line":641},[6271],{"type":20,"tag":64,"props":6272,"children":6273},{"style":2160},[6274],{"type":25,"value":6275},"   // If there's no key (e.g. during a data migration), don't try to transform the data\n",{"type":20,"tag":64,"props":6277,"children":6278},{"class":66,"line":682},[6279,6284,6288,6293,6298,6302,6307,6312],{"type":20,"tag":64,"props":6280,"children":6281},{"style":71},[6282],{"type":25,"value":6283},"   if",{"type":20,"tag":64,"props":6285,"children":6286},{"style":93},[6287],{"type":25,"value":868},{"type":20,"tag":64,"props":6289,"children":6290},{"style":142},[6291],{"type":25,"value":6292},"nil",{"type":20,"tag":64,"props":6294,"children":6295},{"style":71},[6296],{"type":25,"value":6297}," ==",{"type":20,"tag":64,"props":6299,"children":6300},{"style":93},[6301],{"type":25,"value":6068},{"type":20,"tag":64,"props":6303,"children":6304},{"style":142},[6305],{"type":25,"value":6306},"self",{"type":20,"tag":64,"props":6308,"children":6309},{"style":142},[6310],{"type":25,"value":6311}," key",{"type":20,"tag":64,"props":6313,"children":6314},{"style":93},[6315],{"type":25,"value":6316},"])\n",{"type":20,"tag":64,"props":6318,"children":6319},{"class":66,"line":699},[6320],{"type":20,"tag":64,"props":6321,"children":6322},{"style":93},[6323],{"type":25,"value":6324},"   {\n",{"type":20,"tag":64,"props":6326,"children":6327},{"class":66,"line":709},[6328,6333],{"type":20,"tag":64,"props":6329,"children":6330},{"style":71},[6331],{"type":25,"value":6332},"      return",{"type":20,"tag":64,"props":6334,"children":6335},{"style":93},[6336],{"type":25,"value":6337}," data;\n",{"type":20,"tag":64,"props":6339,"children":6340},{"class":66,"line":727},[6341],{"type":20,"tag":64,"props":6342,"children":6343},{"style":93},[6344],{"type":25,"value":6345},"   }\n",{"type":20,"tag":64,"props":6347,"children":6348},{"class":66,"line":2407},[6349],{"type":20,"tag":64,"props":6350,"children":6351},{"emptyLinePlaceholder":703},[6352],{"type":25,"value":706},{"type":20,"tag":64,"props":6354,"children":6355},{"class":66,"line":2415},[6356,6360,6364,6368,6372],{"type":20,"tag":64,"props":6357,"children":6358},{"style":71},[6359],{"type":25,"value":6283},{"type":20,"tag":64,"props":6361,"children":6362},{"style":93},[6363],{"type":25,"value":868},{"type":20,"tag":64,"props":6365,"children":6366},{"style":142},[6367],{"type":25,"value":6292},{"type":20,"tag":64,"props":6369,"children":6370},{"style":71},[6371],{"type":25,"value":6297},{"type":20,"tag":64,"props":6373,"children":6374},{"style":93},[6375],{"type":25,"value":6376}," data)\n",{"type":20,"tag":64,"props":6378,"children":6379},{"class":66,"line":2424},[6380],{"type":20,"tag":64,"props":6381,"children":6382},{"style":93},[6383],{"type":25,"value":6324},{"type":20,"tag":64,"props":6385,"children":6386},{"class":66,"line":2432},[6387,6391,6396],{"type":20,"tag":64,"props":6388,"children":6389},{"style":71},[6390],{"type":25,"value":6332},{"type":20,"tag":64,"props":6392,"children":6393},{"style":142},[6394],{"type":25,"value":6395}," nil",{"type":20,"tag":64,"props":6397,"children":6398},{"style":93},[6399],{"type":25,"value":169},{"type":20,"tag":64,"props":6401,"children":6402},{"class":66,"line":2450},[6403],{"type":20,"tag":64,"props":6404,"children":6405},{"style":93},[6406],{"type":25,"value":6345},{"type":20,"tag":64,"props":6408,"children":6409},{"class":66,"line":2468},[6410],{"type":20,"tag":64,"props":6411,"children":6412},{"emptyLinePlaceholder":703},[6413],{"type":25,"value":706},{"type":20,"tag":64,"props":6415,"children":6416},{"class":66,"line":2500},[6417,6421,6426,6431,6435,6439,6443],{"type":20,"tag":64,"props":6418,"children":6419},{"style":71},[6420],{"type":25,"value":6063},{"type":20,"tag":64,"props":6422,"children":6423},{"style":93},[6424],{"type":25,"value":6425}," [data ",{"type":20,"tag":64,"props":6427,"children":6428},{"style":142},[6429],{"type":25,"value":6430},"dataAES256EncryptedWithKey:",{"type":20,"tag":64,"props":6432,"children":6433},{"style":93},[6434],{"type":25,"value":2137},{"type":20,"tag":64,"props":6436,"children":6437},{"style":142},[6438],{"type":25,"value":6306},{"type":20,"tag":64,"props":6440,"children":6441},{"style":142},[6442],{"type":25,"value":6311},{"type":20,"tag":64,"props":6444,"children":6445},{"style":93},[6446],{"type":25,"value":6447},"]];\n",{"type":20,"tag":64,"props":6449,"children":6450},{"class":66,"line":2556},[6451],{"type":20,"tag":64,"props":6452,"children":6453},{"style":93},[6454],{"type":25,"value":733},{"type":20,"tag":64,"props":6456,"children":6457},{"class":66,"line":2574},[6458],{"type":20,"tag":64,"props":6459,"children":6460},{"emptyLinePlaceholder":703},[6461],{"type":25,"value":706},{"type":20,"tag":64,"props":6463,"children":6464},{"class":66,"line":2675},[6465,6469,6473,6477,6482,6486,6490,6494],{"type":20,"tag":64,"props":6466,"children":6467},{"style":93},[6468],{"type":25,"value":5957},{"type":20,"tag":64,"props":6470,"children":6471},{"style":71},[6472],{"type":25,"value":6234},{"type":20,"tag":64,"props":6474,"children":6475},{"style":93},[6476],{"type":25,"value":2251},{"type":20,"tag":64,"props":6478,"children":6479},{"style":87},[6480],{"type":25,"value":6481},"reverseTransformedValue:",{"type":20,"tag":64,"props":6483,"children":6484},{"style":93},[6485],{"type":25,"value":96},{"type":20,"tag":64,"props":6487,"children":6488},{"style":142},[6489],{"type":25,"value":5870},{"type":20,"tag":64,"props":6491,"children":6492},{"style":71},[6493],{"type":25,"value":893},{"type":20,"tag":64,"props":6495,"children":6496},{"style":93},[6497],{"type":25,"value":6260},{"type":20,"tag":64,"props":6499,"children":6500},{"class":66,"line":2692},[6501],{"type":20,"tag":64,"props":6502,"children":6503},{"style":93},[6504],{"type":25,"value":120},{"type":20,"tag":64,"props":6506,"children":6507},{"class":66,"line":2709},[6508],{"type":20,"tag":64,"props":6509,"children":6510},{"style":2160},[6511],{"type":25,"value":6275},{"type":20,"tag":64,"props":6513,"children":6514},{"class":66,"line":2718},[6515,6519,6523,6527,6531,6535,6539,6543],{"type":20,"tag":64,"props":6516,"children":6517},{"style":71},[6518],{"type":25,"value":6283},{"type":20,"tag":64,"props":6520,"children":6521},{"style":93},[6522],{"type":25,"value":868},{"type":20,"tag":64,"props":6524,"children":6525},{"style":142},[6526],{"type":25,"value":6292},{"type":20,"tag":64,"props":6528,"children":6529},{"style":71},[6530],{"type":25,"value":6297},{"type":20,"tag":64,"props":6532,"children":6533},{"style":93},[6534],{"type":25,"value":6068},{"type":20,"tag":64,"props":6536,"children":6537},{"style":142},[6538],{"type":25,"value":6306},{"type":20,"tag":64,"props":6540,"children":6541},{"style":142},[6542],{"type":25,"value":6311},{"type":20,"tag":64,"props":6544,"children":6545},{"style":93},[6546],{"type":25,"value":6316},{"type":20,"tag":64,"props":6548,"children":6549},{"class":66,"line":2726},[6550],{"type":20,"tag":64,"props":6551,"children":6552},{"style":93},[6553],{"type":25,"value":6324},{"type":20,"tag":64,"props":6555,"children":6556},{"class":66,"line":2798},[6557,6561],{"type":20,"tag":64,"props":6558,"children":6559},{"style":71},[6560],{"type":25,"value":6332},{"type":20,"tag":64,"props":6562,"children":6563},{"style":93},[6564],{"type":25,"value":6337},{"type":20,"tag":64,"props":6566,"children":6567},{"class":66,"line":2849},[6568],{"type":20,"tag":64,"props":6569,"children":6570},{"style":93},[6571],{"type":25,"value":6345},{"type":20,"tag":64,"props":6573,"children":6574},{"class":66,"line":2866},[6575],{"type":20,"tag":64,"props":6576,"children":6577},{"emptyLinePlaceholder":703},[6578],{"type":25,"value":706},{"type":20,"tag":64,"props":6580,"children":6581},{"class":66,"line":2874},[6582,6586,6590,6594,6598],{"type":20,"tag":64,"props":6583,"children":6584},{"style":71},[6585],{"type":25,"value":6283},{"type":20,"tag":64,"props":6587,"children":6588},{"style":93},[6589],{"type":25,"value":868},{"type":20,"tag":64,"props":6591,"children":6592},{"style":142},[6593],{"type":25,"value":6292},{"type":20,"tag":64,"props":6595,"children":6596},{"style":71},[6597],{"type":25,"value":6297},{"type":20,"tag":64,"props":6599,"children":6600},{"style":93},[6601],{"type":25,"value":6376},{"type":20,"tag":64,"props":6603,"children":6604},{"class":66,"line":2919},[6605],{"type":20,"tag":64,"props":6606,"children":6607},{"style":93},[6608],{"type":25,"value":6324},{"type":20,"tag":64,"props":6610,"children":6611},{"class":66,"line":2961},[6612,6616,6620],{"type":20,"tag":64,"props":6613,"children":6614},{"style":71},[6615],{"type":25,"value":6332},{"type":20,"tag":64,"props":6617,"children":6618},{"style":142},[6619],{"type":25,"value":6395},{"type":20,"tag":64,"props":6621,"children":6622},{"style":93},[6623],{"type":25,"value":169},{"type":20,"tag":64,"props":6625,"children":6626},{"class":66,"line":2984},[6627],{"type":20,"tag":64,"props":6628,"children":6629},{"style":93},[6630],{"type":25,"value":6345},{"type":20,"tag":64,"props":6632,"children":6633},{"class":66,"line":3005},[6634],{"type":20,"tag":64,"props":6635,"children":6636},{"emptyLinePlaceholder":703},[6637],{"type":25,"value":706},{"type":20,"tag":64,"props":6639,"children":6640},{"class":66,"line":3022},[6641,6645,6649,6654,6658,6662,6666],{"type":20,"tag":64,"props":6642,"children":6643},{"style":71},[6644],{"type":25,"value":6063},{"type":20,"tag":64,"props":6646,"children":6647},{"style":93},[6648],{"type":25,"value":6425},{"type":20,"tag":64,"props":6650,"children":6651},{"style":142},[6652],{"type":25,"value":6653},"dataAES256DecryptedWithKey:",{"type":20,"tag":64,"props":6655,"children":6656},{"style":93},[6657],{"type":25,"value":2137},{"type":20,"tag":64,"props":6659,"children":6660},{"style":142},[6661],{"type":25,"value":6306},{"type":20,"tag":64,"props":6663,"children":6664},{"style":142},[6665],{"type":25,"value":6311},{"type":20,"tag":64,"props":6667,"children":6668},{"style":93},[6669],{"type":25,"value":6447},{"type":20,"tag":64,"props":6671,"children":6672},{"class":66,"line":3040},[6673],{"type":20,"tag":64,"props":6674,"children":6675},{"style":93},[6676],{"type":25,"value":733},{"type":20,"tag":64,"props":6678,"children":6679},{"class":66,"line":3054},[6680],{"type":20,"tag":64,"props":6681,"children":6682},{"emptyLinePlaceholder":703},[6683],{"type":25,"value":706},{"type":20,"tag":64,"props":6685,"children":6686},{"class":66,"line":3063},[6687],{"type":20,"tag":64,"props":6688,"children":6689},{"style":71},[6690],{"type":25,"value":5993},{"type":20,"tag":21,"props":6692,"children":6693},{},[6694,6696,6700],{"type":25,"value":6695},"The ",{"type":20,"tag":1045,"props":6697,"children":6698},{},[6699],{"type":25,"value":5863},{"type":25,"value":6701}," method might get the secret key from any number of places, such as a password requested at login and stored in the app delegate. I'll touch on the NSData category methods that actually perform the encryption in a little bit.",{"type":20,"tag":21,"props":6703,"children":6704},{},[6705],{"type":25,"value":6706},"This encryption class can then easily be subclassed to handle different data types, like strings, dates, numbers, etc. Here's an example string encryption class that converts between NSString and NSData in order to use its parent class transformation methods.",{"type":20,"tag":5874,"props":6708,"children":6710},{"id":6709},"encryptiontransformerh-1",[6711],{"type":25,"value":5879},{"type":20,"tag":53,"props":6713,"children":6715},{"className":5882,"code":6714,"language":5884,"meta":8,"style":8},"@interface StringEncryptionTransformer : EncryptionTransformer\n{}\n",[6716],{"type":20,"tag":60,"props":6717,"children":6718},{"__ignoreMap":8},[6719,6740],{"type":20,"tag":64,"props":6720,"children":6721},{"class":66,"line":67},[6722,6726,6731,6735],{"type":20,"tag":64,"props":6723,"children":6724},{"style":71},[6725],{"type":25,"value":5896},{"type":20,"tag":64,"props":6727,"children":6728},{"style":87},[6729],{"type":25,"value":6730}," StringEncryptionTransformer",{"type":20,"tag":64,"props":6732,"children":6733},{"style":93},[6734],{"type":25,"value":5906},{"type":20,"tag":64,"props":6736,"children":6737},{"style":87},[6738],{"type":25,"value":6739},"EncryptionTransformer\n",{"type":20,"tag":64,"props":6741,"children":6742},{"class":66,"line":114},[6743],{"type":20,"tag":64,"props":6744,"children":6745},{"style":93},[6746],{"type":25,"value":5919},{"type":20,"tag":6748,"props":6749,"children":6751},"h4",{"id":6750},"encryptiontransformerm-1",[6752],{"type":25,"value":5999},{"type":20,"tag":53,"props":6754,"children":6756},{"className":5882,"code":6755,"language":5884,"meta":8,"style":8},"@implementation StringEncryptionTransformer\n\n+ (Class)transformedValueClass\n{\n   return [NSString class];\n}\n\n- (id)transformedValue:(NSString*)string\n{\n   NSData* data = [string dataUsingEncoding:NSUTF8StringEncoding];\n   return [super transformedValue:data];\n}\n\n- (id)reverseTransformedValue:(NSData*)data\n{\n   if (nil == data)\n   {\n      return nil;\n   }\n\n   data = [super reverseTransformedValue:data];\n\n   return [[[NSString alloc] initWithBytes:[data bytes]\n                                    length:[data length]\n                                  encoding:NSUTF8StringEncoding]\n           autorelease];\n}\n\n@end\n",[6757],{"type":20,"tag":60,"props":6758,"children":6759},{"__ignoreMap":8},[6760,6772,6779,6798,6805,6828,6835,6842,6878,6885,6920,6946,6953,6960,6995,7002,7025,7032,7047,7054,7061,7090,7097,7142,7163,7175,7183,7190,7197],{"type":20,"tag":64,"props":6761,"children":6762},{"class":66,"line":67},[6763,6767],{"type":20,"tag":64,"props":6764,"children":6765},{"style":71},[6766],{"type":25,"value":6014},{"type":20,"tag":64,"props":6768,"children":6769},{"style":87},[6770],{"type":25,"value":6771}," StringEncryptionTransformer\n",{"type":20,"tag":64,"props":6773,"children":6774},{"class":66,"line":114},[6775],{"type":20,"tag":64,"props":6776,"children":6777},{"emptyLinePlaceholder":703},[6778],{"type":25,"value":706},{"type":20,"tag":64,"props":6780,"children":6781},{"class":66,"line":123},[6782,6786,6790,6794],{"type":20,"tag":64,"props":6783,"children":6784},{"style":93},[6785],{"type":25,"value":6034},{"type":20,"tag":64,"props":6787,"children":6788},{"style":71},[6789],{"type":25,"value":6039},{"type":20,"tag":64,"props":6791,"children":6792},{"style":93},[6793],{"type":25,"value":2251},{"type":20,"tag":64,"props":6795,"children":6796},{"style":87},[6797],{"type":25,"value":6048},{"type":20,"tag":64,"props":6799,"children":6800},{"class":66,"line":152},[6801],{"type":20,"tag":64,"props":6802,"children":6803},{"style":93},[6804],{"type":25,"value":120},{"type":20,"tag":64,"props":6806,"children":6807},{"class":66,"line":172},[6808,6812,6816,6820,6824],{"type":20,"tag":64,"props":6809,"children":6810},{"style":71},[6811],{"type":25,"value":6063},{"type":20,"tag":64,"props":6813,"children":6814},{"style":93},[6815],{"type":25,"value":6068},{"type":20,"tag":64,"props":6817,"children":6818},{"style":142},[6819],{"type":25,"value":5962},{"type":20,"tag":64,"props":6821,"children":6822},{"style":142},[6823],{"type":25,"value":6077},{"type":20,"tag":64,"props":6825,"children":6826},{"style":93},[6827],{"type":25,"value":2147},{"type":20,"tag":64,"props":6829,"children":6830},{"class":66,"line":218},[6831],{"type":20,"tag":64,"props":6832,"children":6833},{"style":93},[6834],{"type":25,"value":733},{"type":20,"tag":64,"props":6836,"children":6837},{"class":66,"line":235},[6838],{"type":20,"tag":64,"props":6839,"children":6840},{"emptyLinePlaceholder":703},[6841],{"type":25,"value":706},{"type":20,"tag":64,"props":6843,"children":6844},{"class":66,"line":276},[6845,6849,6853,6857,6861,6865,6869,6873],{"type":20,"tag":64,"props":6846,"children":6847},{"style":93},[6848],{"type":25,"value":5957},{"type":20,"tag":64,"props":6850,"children":6851},{"style":71},[6852],{"type":25,"value":6234},{"type":20,"tag":64,"props":6854,"children":6855},{"style":93},[6856],{"type":25,"value":2251},{"type":20,"tag":64,"props":6858,"children":6859},{"style":87},[6860],{"type":25,"value":6243},{"type":20,"tag":64,"props":6862,"children":6863},{"style":93},[6864],{"type":25,"value":96},{"type":20,"tag":64,"props":6866,"children":6867},{"style":142},[6868],{"type":25,"value":5962},{"type":20,"tag":64,"props":6870,"children":6871},{"style":71},[6872],{"type":25,"value":893},{"type":20,"tag":64,"props":6874,"children":6875},{"style":93},[6876],{"type":25,"value":6877},")string\n",{"type":20,"tag":64,"props":6879,"children":6880},{"class":66,"line":293},[6881],{"type":20,"tag":64,"props":6882,"children":6883},{"style":93},[6884],{"type":25,"value":120},{"type":20,"tag":64,"props":6886,"children":6887},{"class":66,"line":334},[6888,6893,6897,6902,6906,6911,6916],{"type":20,"tag":64,"props":6889,"children":6890},{"style":142},[6891],{"type":25,"value":6892},"   NSData",{"type":20,"tag":64,"props":6894,"children":6895},{"style":71},[6896],{"type":25,"value":893},{"type":20,"tag":64,"props":6898,"children":6899},{"style":93},[6900],{"type":25,"value":6901}," data ",{"type":20,"tag":64,"props":6903,"children":6904},{"style":71},[6905],{"type":25,"value":1682},{"type":20,"tag":64,"props":6907,"children":6908},{"style":93},[6909],{"type":25,"value":6910}," [string ",{"type":20,"tag":64,"props":6912,"children":6913},{"style":142},[6914],{"type":25,"value":6915},"dataUsingEncoding:NSUTF8StringEncoding",{"type":20,"tag":64,"props":6917,"children":6918},{"style":93},[6919],{"type":25,"value":2147},{"type":20,"tag":64,"props":6921,"children":6922},{"class":66,"line":351},[6923,6927,6931,6936,6941],{"type":20,"tag":64,"props":6924,"children":6925},{"style":71},[6926],{"type":25,"value":6063},{"type":20,"tag":64,"props":6928,"children":6929},{"style":93},[6930],{"type":25,"value":6068},{"type":20,"tag":64,"props":6932,"children":6933},{"style":142},[6934],{"type":25,"value":6935},"super",{"type":20,"tag":64,"props":6937,"children":6938},{"style":142},[6939],{"type":25,"value":6940}," transformedValue:",{"type":20,"tag":64,"props":6942,"children":6943},{"style":93},[6944],{"type":25,"value":6945},"data];\n",{"type":20,"tag":64,"props":6947,"children":6948},{"class":66,"line":392},[6949],{"type":20,"tag":64,"props":6950,"children":6951},{"style":93},[6952],{"type":25,"value":733},{"type":20,"tag":64,"props":6954,"children":6955},{"class":66,"line":409},[6956],{"type":20,"tag":64,"props":6957,"children":6958},{"emptyLinePlaceholder":703},[6959],{"type":25,"value":706},{"type":20,"tag":64,"props":6961,"children":6962},{"class":66,"line":450},[6963,6967,6971,6975,6979,6983,6987,6991],{"type":20,"tag":64,"props":6964,"children":6965},{"style":93},[6966],{"type":25,"value":5957},{"type":20,"tag":64,"props":6968,"children":6969},{"style":71},[6970],{"type":25,"value":6234},{"type":20,"tag":64,"props":6972,"children":6973},{"style":93},[6974],{"type":25,"value":2251},{"type":20,"tag":64,"props":6976,"children":6977},{"style":87},[6978],{"type":25,"value":6481},{"type":20,"tag":64,"props":6980,"children":6981},{"style":93},[6982],{"type":25,"value":96},{"type":20,"tag":64,"props":6984,"children":6985},{"style":142},[6986],{"type":25,"value":5870},{"type":20,"tag":64,"props":6988,"children":6989},{"style":71},[6990],{"type":25,"value":893},{"type":20,"tag":64,"props":6992,"children":6993},{"style":93},[6994],{"type":25,"value":6260},{"type":20,"tag":64,"props":6996,"children":6997},{"class":66,"line":467},[6998],{"type":20,"tag":64,"props":6999,"children":7000},{"style":93},[7001],{"type":25,"value":120},{"type":20,"tag":64,"props":7003,"children":7004},{"class":66,"line":508},[7005,7009,7013,7017,7021],{"type":20,"tag":64,"props":7006,"children":7007},{"style":71},[7008],{"type":25,"value":6283},{"type":20,"tag":64,"props":7010,"children":7011},{"style":93},[7012],{"type":25,"value":868},{"type":20,"tag":64,"props":7014,"children":7015},{"style":142},[7016],{"type":25,"value":6292},{"type":20,"tag":64,"props":7018,"children":7019},{"style":71},[7020],{"type":25,"value":6297},{"type":20,"tag":64,"props":7022,"children":7023},{"style":93},[7024],{"type":25,"value":6376},{"type":20,"tag":64,"props":7026,"children":7027},{"class":66,"line":525},[7028],{"type":20,"tag":64,"props":7029,"children":7030},{"style":93},[7031],{"type":25,"value":6324},{"type":20,"tag":64,"props":7033,"children":7034},{"class":66,"line":566},[7035,7039,7043],{"type":20,"tag":64,"props":7036,"children":7037},{"style":71},[7038],{"type":25,"value":6332},{"type":20,"tag":64,"props":7040,"children":7041},{"style":142},[7042],{"type":25,"value":6395},{"type":20,"tag":64,"props":7044,"children":7045},{"style":93},[7046],{"type":25,"value":169},{"type":20,"tag":64,"props":7048,"children":7049},{"class":66,"line":583},[7050],{"type":20,"tag":64,"props":7051,"children":7052},{"style":93},[7053],{"type":25,"value":6345},{"type":20,"tag":64,"props":7055,"children":7056},{"class":66,"line":624},[7057],{"type":20,"tag":64,"props":7058,"children":7059},{"emptyLinePlaceholder":703},[7060],{"type":25,"value":706},{"type":20,"tag":64,"props":7062,"children":7063},{"class":66,"line":641},[7064,7069,7073,7077,7081,7086],{"type":20,"tag":64,"props":7065,"children":7066},{"style":93},[7067],{"type":25,"value":7068},"   data ",{"type":20,"tag":64,"props":7070,"children":7071},{"style":71},[7072],{"type":25,"value":1682},{"type":20,"tag":64,"props":7074,"children":7075},{"style":93},[7076],{"type":25,"value":6068},{"type":20,"tag":64,"props":7078,"children":7079},{"style":142},[7080],{"type":25,"value":6935},{"type":20,"tag":64,"props":7082,"children":7083},{"style":142},[7084],{"type":25,"value":7085}," reverseTransformedValue:",{"type":20,"tag":64,"props":7087,"children":7088},{"style":93},[7089],{"type":25,"value":6945},{"type":20,"tag":64,"props":7091,"children":7092},{"class":66,"line":682},[7093],{"type":20,"tag":64,"props":7094,"children":7095},{"emptyLinePlaceholder":703},[7096],{"type":25,"value":706},{"type":20,"tag":64,"props":7098,"children":7099},{"class":66,"line":699},[7100,7104,7109,7113,7118,7122,7127,7132,7137],{"type":20,"tag":64,"props":7101,"children":7102},{"style":71},[7103],{"type":25,"value":6063},{"type":20,"tag":64,"props":7105,"children":7106},{"style":93},[7107],{"type":25,"value":7108}," [[[",{"type":20,"tag":64,"props":7110,"children":7111},{"style":142},[7112],{"type":25,"value":5962},{"type":20,"tag":64,"props":7114,"children":7115},{"style":142},[7116],{"type":25,"value":7117}," alloc",{"type":20,"tag":64,"props":7119,"children":7120},{"style":93},[7121],{"type":25,"value":2938},{"type":20,"tag":64,"props":7123,"children":7124},{"style":142},[7125],{"type":25,"value":7126},"initWithBytes:",{"type":20,"tag":64,"props":7128,"children":7129},{"style":93},[7130],{"type":25,"value":7131},"[data ",{"type":20,"tag":64,"props":7133,"children":7134},{"style":142},[7135],{"type":25,"value":7136},"bytes",{"type":20,"tag":64,"props":7138,"children":7139},{"style":93},[7140],{"type":25,"value":7141},"]\n",{"type":20,"tag":64,"props":7143,"children":7144},{"class":66,"line":709},[7145,7150,7154,7159],{"type":20,"tag":64,"props":7146,"children":7147},{"style":142},[7148],{"type":25,"value":7149},"                                    length:",{"type":20,"tag":64,"props":7151,"children":7152},{"style":93},[7153],{"type":25,"value":7131},{"type":20,"tag":64,"props":7155,"children":7156},{"style":142},[7157],{"type":25,"value":7158},"length",{"type":20,"tag":64,"props":7160,"children":7161},{"style":93},[7162],{"type":25,"value":7141},{"type":20,"tag":64,"props":7164,"children":7165},{"class":66,"line":727},[7166,7171],{"type":20,"tag":64,"props":7167,"children":7168},{"style":142},[7169],{"type":25,"value":7170},"                                  encoding:NSUTF8StringEncoding",{"type":20,"tag":64,"props":7172,"children":7173},{"style":93},[7174],{"type":25,"value":7141},{"type":20,"tag":64,"props":7176,"children":7177},{"class":66,"line":2407},[7178],{"type":20,"tag":64,"props":7179,"children":7180},{"style":93},[7181],{"type":25,"value":7182},"           autorelease];\n",{"type":20,"tag":64,"props":7184,"children":7185},{"class":66,"line":2415},[7186],{"type":20,"tag":64,"props":7187,"children":7188},{"style":93},[7189],{"type":25,"value":733},{"type":20,"tag":64,"props":7191,"children":7192},{"class":66,"line":2424},[7193],{"type":20,"tag":64,"props":7194,"children":7195},{"emptyLinePlaceholder":703},[7196],{"type":25,"value":706},{"type":20,"tag":64,"props":7198,"children":7199},{"class":66,"line":2432},[7200],{"type":20,"tag":64,"props":7201,"children":7202},{"style":71},[7203],{"type":25,"value":5993},{"type":20,"tag":21,"props":7205,"children":7206},{},[7207,7209,7214,7216,7221,7223,7228,7230,7235],{"type":25,"value":7208},"Once these classes are set up, the Core Data model editor lets you assign an entity ",{"type":20,"tag":776,"props":7210,"children":7211},{},[7212],{"type":25,"value":7213},"attribute type",{"type":25,"value":7215}," of ",{"type":20,"tag":1045,"props":7217,"children":7218},{},[7219],{"type":25,"value":7220},"Transformable",{"type":25,"value":7222}," and a ",{"type":20,"tag":776,"props":7224,"children":7225},{},[7226],{"type":25,"value":7227},"name",{"type":25,"value":7229}," of the NSValueTransformer class, such as ",{"type":20,"tag":1045,"props":7231,"children":7232},{},[7233],{"type":25,"value":7234},"StringEncryptionTransformer",{"type":25,"value":1569},{"type":20,"tag":21,"props":7237,"children":7238},{},[7239,7245],{"type":20,"tag":7240,"props":7241,"children":7244},"img",{"alt":8,"src":7242,"title":7243},"/nharrison/2012-07/img/core-data-editor1.png","Core Data editor",[],{"type":25,"value":7246}," Core Data model editor in Xcode showing an entity's Transformable attribute.",{"type":20,"tag":21,"props":7248,"children":7249},{},[7250,7252,7258],{"type":25,"value":7251},"Now, these attributes can be written to in code just like any other (e.g. ",{"type":20,"tag":60,"props":7253,"children":7255},{"className":7254},[],[7256],{"type":25,"value":7257},"clark.secretIdentity = @\"superman\"",{"type":25,"value":7259},"), but when they are persisted to the underlying SQLite database (or other sort of data store), the appropriate NSValueTransformer class will be called to encrypt the values before writing them to the data store.",{"type":20,"tag":21,"props":7261,"children":7262},{},[7263],{"type":25,"value":7264},"Likewise, at the time a persisted object is read from the data store, the NSValueTransformer class will decrypt it. Encryption and decryption is thus lazy and only performed when an object is used or updated -- no need to decrypt an entire file or database during app startup.",{"type":20,"tag":1023,"props":7266,"children":7268},{"id":7267},"aes-256-encryption-category",[7269],{"type":25,"value":7270},"AES-256 encryption category",{"type":20,"tag":21,"props":7272,"children":7273},{},[7274,7276,7283,7285,7292,7294,7301],{"type":25,"value":7275},"There are a number of example classes that make performing ",{"type":20,"tag":28,"props":7277,"children":7280},{"href":7278,"rel":7279},"http://en.wikipedia.org/wiki/Advanced_Encryption_Standard",[32],[7281],{"type":25,"value":7282},"AES-256",{"type":25,"value":7284}," encryption as simple as shown above, such as Jim Dovey's ",{"type":20,"tag":28,"props":7286,"children":7289},{"href":7287,"rel":7288},"https://github.com/AlanQuatermain/aqtoolkit/tree/master/CommonCrypto",[32],[7290],{"type":25,"value":7291},"NSData+CommonCrypto category",{"type":25,"value":7293}," and this ",{"type":20,"tag":28,"props":7295,"children":7298},{"href":7296,"rel":7297},"http://pastie.org/426530",[32],[7299],{"type":25,"value":7300},"unattributed snippet",{"type":25,"value":7302},".  The better ones use encryption libraries provided by Apple, which may (or may not, IANAL) mean that you don't need a CCATS form for app submission.",{"type":20,"tag":21,"props":7304,"children":7305},{},[7306,7308,7314,7316,7322,7324,7330,7332,7339],{"type":25,"value":7307},"However, one major caveat to encrypting attributes individually is that patterns from short, repeated values will naturally rise.  If you are encrypting only a couple different possible values for an attribute (e.g. \"superhero\" and \"evildoer\"), simple encryption using the same key will result in only two encrypted values.  That is, for the key \"",{"type":20,"tag":60,"props":7309,"children":7311},{"className":7310},[],[7312],{"type":25,"value":7313},"top secret",{"type":25,"value":7315},"\", the value \"",{"type":20,"tag":60,"props":7317,"children":7319},{"className":7318},[],[7320],{"type":25,"value":7321},"Superman",{"type":25,"value":7323},"\" will always encrypt to \"",{"type":20,"tag":60,"props":7325,"children":7327},{"className":7326},[],[7328],{"type":25,"value":7329},"?b64JzJ4aC0IhKaf7xeTWaglC6L/3VFxwA5XVrfDRntxebO4rFUSdNNrzfVFIU3yZH0F?64b",{"type":25,"value":7331},"\" (",{"type":20,"tag":28,"props":7333,"children":7336},{"href":7334,"rel":7335},"http://www.fourmilab.ch/javascrypt/javascrypt.html",[32],[7337],{"type":25,"value":7338},"Javascrypt",{"type":25,"value":7340}," is a handy online tool for encryption).",{"type":20,"tag":21,"props":7342,"children":7343},{},[7344,7346,7356,7358,7365],{"type":25,"value":7345},"Enter the ",{"type":20,"tag":28,"props":7347,"children":7350},{"href":7348,"rel":7349},"http://en.wikipedia.org/wiki/Initialization_vector",[32],[7351],{"type":20,"tag":1045,"props":7352,"children":7353},{},[7354],{"type":25,"value":7355},"initialization vector",{"type":25,"value":7357}," (IV), which like the ",{"type":20,"tag":28,"props":7359,"children":7362},{"href":7360,"rel":7361},"http://en.wikipedia.org/wiki/Salt_%28cryptography%29",[32],[7363],{"type":25,"value":7364},"salt",{"type":25,"value":7366}," for a password helps hide patterns by randomizing encryption input.  The IV should be:",{"type":20,"tag":1035,"props":7368,"children":7369},{},[7370,7382,7387,7392],{"type":20,"tag":1039,"props":7371,"children":7372},{},[7373,7375],{"type":25,"value":7374},"a random number, for example the result of ",{"type":20,"tag":28,"props":7376,"children":7379},{"href":7377,"rel":7378},"https://developer.apple.com/library/mac/#documentation/Darwin/Reference/Manpages/man3/arc4random.3.html",[32],[7380],{"type":25,"value":7381},"arc4random()",{"type":20,"tag":1039,"props":7383,"children":7384},{},[7385],{"type":25,"value":7386},"different for every attribute, or at least every entity",{"type":20,"tag":1039,"props":7388,"children":7389},{},[7390],{"type":25,"value":7391},"stored alongside the encrypted value, since the same IV used for encryption is necessary for decryption",{"type":20,"tag":1039,"props":7393,"children":7394},{},[7395],{"type":25,"value":7396},"public, that is it need not (and should not) be encrypted",{"type":20,"tag":21,"props":7398,"children":7399},{},[7400],{"type":25,"value":7401},"Unfortunately, many example code snippets that call CCCrypt (including one linked above) leave the initialization vector parameter as simply:",{"type":20,"tag":21,"props":7403,"children":7404},{},[7405],{"type":20,"tag":60,"props":7406,"children":7408},{"className":7407},[],[7409],{"type":25,"value":7410},"NULL / _initialization vector (optional)_ /,",{"type":20,"tag":21,"props":7412,"children":7413},{},[7414],{"type":25,"value":7415},"Rather than follow suit, it's simple to update our EncryptionTransformer to generate a IV and prepend it to the encrypted data:",{"type":20,"tag":6748,"props":7417,"children":7419},{"id":7418},"encryptiontransformermencryptiontransformerm",[7420],{"type":25,"value":7421},"EncryptionTransformer.mEncryptionTransformer.m",{"type":20,"tag":53,"props":7423,"children":7425},{"className":5882,"code":7424,"language":5884,"meta":8,"style":8},"- (id)transformedValue:(NSData*)data\n{\n   ...\n\n   // Use another NSData category method (left as an exercise \n   // to the reader) to randomly generate the IV data\n   NSData* iv = [NSData randomDataOfLength:32];\n\n   data = [data dataAES256EncryptedWithKey:[self key] Iv:iv];\n\n   // Return a data object that includes the IV with the \n   // encrypted data appended\n   NSMutableData* mutableData = [NSMutableData dataWithData:iv];\n   [mutableData appendData:data];\n   return mutableData;\n}\n\n- (id)reverseTransformedValue:(NSData*)data\n{\n   ...\n\n   // The IV was stored in the first 32 bytes of the data\n   NSData* iv = [data subdataWithRange:NSMakeRange(0, 32)];\n\n   // Remove the IV from the encrypted data and decrypt it\n   NSMutableData* mutableData = [NSMutableData dataWithData:data];\n   [mutableData replaceBytesInRange:NSMakeRange(0, 32) withBytes:NULL];\n   return [mutableData dataAES256DecryptedWithKey:[self key] Iv:iv];\n}\n",[7426],{"type":20,"tag":60,"props":7427,"children":7428},{"__ignoreMap":8},[7429,7461,7468,7476,7483,7491,7499,7536,7543,7588,7595,7603,7611,7650,7667,7679,7686,7693,7725,7732,7739,7746,7754,7804,7811,7819,7854,7895,7935],{"type":20,"tag":64,"props":7430,"children":7431},{"class":66,"line":67},[7432,7436,7440,7444,7449,7453,7457],{"type":20,"tag":64,"props":7433,"children":7434},{"style":71},[7435],{"type":25,"value":1438},{"type":20,"tag":64,"props":7437,"children":7438},{"style":93},[7439],{"type":25,"value":868},{"type":20,"tag":64,"props":7441,"children":7442},{"style":71},[7443],{"type":25,"value":6234},{"type":20,"tag":64,"props":7445,"children":7446},{"style":93},[7447],{"type":25,"value":7448},")transformedValue:(",{"type":20,"tag":64,"props":7450,"children":7451},{"style":142},[7452],{"type":25,"value":5870},{"type":20,"tag":64,"props":7454,"children":7455},{"style":71},[7456],{"type":25,"value":893},{"type":20,"tag":64,"props":7458,"children":7459},{"style":93},[7460],{"type":25,"value":6260},{"type":20,"tag":64,"props":7462,"children":7463},{"class":66,"line":114},[7464],{"type":20,"tag":64,"props":7465,"children":7466},{"style":93},[7467],{"type":25,"value":120},{"type":20,"tag":64,"props":7469,"children":7470},{"class":66,"line":123},[7471],{"type":20,"tag":64,"props":7472,"children":7473},{"style":93},[7474],{"type":25,"value":7475},"   ...\n",{"type":20,"tag":64,"props":7477,"children":7478},{"class":66,"line":152},[7479],{"type":20,"tag":64,"props":7480,"children":7481},{"emptyLinePlaceholder":703},[7482],{"type":25,"value":706},{"type":20,"tag":64,"props":7484,"children":7485},{"class":66,"line":172},[7486],{"type":20,"tag":64,"props":7487,"children":7488},{"style":2160},[7489],{"type":25,"value":7490},"   // Use another NSData category method (left as an exercise \n",{"type":20,"tag":64,"props":7492,"children":7493},{"class":66,"line":218},[7494],{"type":20,"tag":64,"props":7495,"children":7496},{"style":2160},[7497],{"type":25,"value":7498},"   // to the reader) to randomly generate the IV data\n",{"type":20,"tag":64,"props":7500,"children":7501},{"class":66,"line":235},[7502,7506,7510,7515,7519,7523,7527,7532],{"type":20,"tag":64,"props":7503,"children":7504},{"style":142},[7505],{"type":25,"value":6892},{"type":20,"tag":64,"props":7507,"children":7508},{"style":71},[7509],{"type":25,"value":893},{"type":20,"tag":64,"props":7511,"children":7512},{"style":93},[7513],{"type":25,"value":7514}," iv ",{"type":20,"tag":64,"props":7516,"children":7517},{"style":71},[7518],{"type":25,"value":1682},{"type":20,"tag":64,"props":7520,"children":7521},{"style":93},[7522],{"type":25,"value":6068},{"type":20,"tag":64,"props":7524,"children":7525},{"style":142},[7526],{"type":25,"value":5870},{"type":20,"tag":64,"props":7528,"children":7529},{"style":142},[7530],{"type":25,"value":7531}," randomDataOfLength:32",{"type":20,"tag":64,"props":7533,"children":7534},{"style":93},[7535],{"type":25,"value":2147},{"type":20,"tag":64,"props":7537,"children":7538},{"class":66,"line":276},[7539],{"type":20,"tag":64,"props":7540,"children":7541},{"emptyLinePlaceholder":703},[7542],{"type":25,"value":706},{"type":20,"tag":64,"props":7544,"children":7545},{"class":66,"line":293},[7546,7550,7554,7558,7562,7566,7570,7574,7578,7583],{"type":20,"tag":64,"props":7547,"children":7548},{"style":93},[7549],{"type":25,"value":7068},{"type":20,"tag":64,"props":7551,"children":7552},{"style":71},[7553],{"type":25,"value":1682},{"type":20,"tag":64,"props":7555,"children":7556},{"style":93},[7557],{"type":25,"value":6425},{"type":20,"tag":64,"props":7559,"children":7560},{"style":142},[7561],{"type":25,"value":6430},{"type":20,"tag":64,"props":7563,"children":7564},{"style":93},[7565],{"type":25,"value":2137},{"type":20,"tag":64,"props":7567,"children":7568},{"style":142},[7569],{"type":25,"value":6306},{"type":20,"tag":64,"props":7571,"children":7572},{"style":142},[7573],{"type":25,"value":6311},{"type":20,"tag":64,"props":7575,"children":7576},{"style":93},[7577],{"type":25,"value":2938},{"type":20,"tag":64,"props":7579,"children":7580},{"style":142},[7581],{"type":25,"value":7582},"Iv:",{"type":20,"tag":64,"props":7584,"children":7585},{"style":93},[7586],{"type":25,"value":7587},"iv];\n",{"type":20,"tag":64,"props":7589,"children":7590},{"class":66,"line":334},[7591],{"type":20,"tag":64,"props":7592,"children":7593},{"emptyLinePlaceholder":703},[7594],{"type":25,"value":706},{"type":20,"tag":64,"props":7596,"children":7597},{"class":66,"line":351},[7598],{"type":20,"tag":64,"props":7599,"children":7600},{"style":2160},[7601],{"type":25,"value":7602},"   // Return a data object that includes the IV with the \n",{"type":20,"tag":64,"props":7604,"children":7605},{"class":66,"line":392},[7606],{"type":20,"tag":64,"props":7607,"children":7608},{"style":2160},[7609],{"type":25,"value":7610},"   // encrypted data appended\n",{"type":20,"tag":64,"props":7612,"children":7613},{"class":66,"line":409},[7614,7619,7623,7628,7632,7636,7641,7646],{"type":20,"tag":64,"props":7615,"children":7616},{"style":142},[7617],{"type":25,"value":7618},"   NSMutableData",{"type":20,"tag":64,"props":7620,"children":7621},{"style":71},[7622],{"type":25,"value":893},{"type":20,"tag":64,"props":7624,"children":7625},{"style":93},[7626],{"type":25,"value":7627}," mutableData ",{"type":20,"tag":64,"props":7629,"children":7630},{"style":71},[7631],{"type":25,"value":1682},{"type":20,"tag":64,"props":7633,"children":7634},{"style":93},[7635],{"type":25,"value":6068},{"type":20,"tag":64,"props":7637,"children":7638},{"style":142},[7639],{"type":25,"value":7640},"NSMutableData",{"type":20,"tag":64,"props":7642,"children":7643},{"style":142},[7644],{"type":25,"value":7645}," dataWithData:",{"type":20,"tag":64,"props":7647,"children":7648},{"style":93},[7649],{"type":25,"value":7587},{"type":20,"tag":64,"props":7651,"children":7652},{"class":66,"line":450},[7653,7658,7663],{"type":20,"tag":64,"props":7654,"children":7655},{"style":93},[7656],{"type":25,"value":7657},"   [mutableData ",{"type":20,"tag":64,"props":7659,"children":7660},{"style":142},[7661],{"type":25,"value":7662},"appendData:",{"type":20,"tag":64,"props":7664,"children":7665},{"style":93},[7666],{"type":25,"value":6945},{"type":20,"tag":64,"props":7668,"children":7669},{"class":66,"line":467},[7670,7674],{"type":20,"tag":64,"props":7671,"children":7672},{"style":71},[7673],{"type":25,"value":6063},{"type":20,"tag":64,"props":7675,"children":7676},{"style":93},[7677],{"type":25,"value":7678}," mutableData;\n",{"type":20,"tag":64,"props":7680,"children":7681},{"class":66,"line":508},[7682],{"type":20,"tag":64,"props":7683,"children":7684},{"style":93},[7685],{"type":25,"value":733},{"type":20,"tag":64,"props":7687,"children":7688},{"class":66,"line":525},[7689],{"type":20,"tag":64,"props":7690,"children":7691},{"emptyLinePlaceholder":703},[7692],{"type":25,"value":706},{"type":20,"tag":64,"props":7694,"children":7695},{"class":66,"line":566},[7696,7700,7704,7708,7713,7717,7721],{"type":20,"tag":64,"props":7697,"children":7698},{"style":71},[7699],{"type":25,"value":1438},{"type":20,"tag":64,"props":7701,"children":7702},{"style":93},[7703],{"type":25,"value":868},{"type":20,"tag":64,"props":7705,"children":7706},{"style":71},[7707],{"type":25,"value":6234},{"type":20,"tag":64,"props":7709,"children":7710},{"style":93},[7711],{"type":25,"value":7712},")reverseTransformedValue:(",{"type":20,"tag":64,"props":7714,"children":7715},{"style":142},[7716],{"type":25,"value":5870},{"type":20,"tag":64,"props":7718,"children":7719},{"style":71},[7720],{"type":25,"value":893},{"type":20,"tag":64,"props":7722,"children":7723},{"style":93},[7724],{"type":25,"value":6260},{"type":20,"tag":64,"props":7726,"children":7727},{"class":66,"line":583},[7728],{"type":20,"tag":64,"props":7729,"children":7730},{"style":93},[7731],{"type":25,"value":120},{"type":20,"tag":64,"props":7733,"children":7734},{"class":66,"line":624},[7735],{"type":20,"tag":64,"props":7736,"children":7737},{"style":93},[7738],{"type":25,"value":7475},{"type":20,"tag":64,"props":7740,"children":7741},{"class":66,"line":641},[7742],{"type":20,"tag":64,"props":7743,"children":7744},{"emptyLinePlaceholder":703},[7745],{"type":25,"value":706},{"type":20,"tag":64,"props":7747,"children":7748},{"class":66,"line":682},[7749],{"type":20,"tag":64,"props":7750,"children":7751},{"style":2160},[7752],{"type":25,"value":7753},"   // The IV was stored in the first 32 bytes of the data\n",{"type":20,"tag":64,"props":7755,"children":7756},{"class":66,"line":699},[7757,7761,7765,7769,7773,7777,7782,7786,7790,7794,7799],{"type":20,"tag":64,"props":7758,"children":7759},{"style":142},[7760],{"type":25,"value":6892},{"type":20,"tag":64,"props":7762,"children":7763},{"style":71},[7764],{"type":25,"value":893},{"type":20,"tag":64,"props":7766,"children":7767},{"style":93},[7768],{"type":25,"value":7514},{"type":20,"tag":64,"props":7770,"children":7771},{"style":71},[7772],{"type":25,"value":1682},{"type":20,"tag":64,"props":7774,"children":7775},{"style":93},[7776],{"type":25,"value":6425},{"type":20,"tag":64,"props":7778,"children":7779},{"style":142},[7780],{"type":25,"value":7781},"subdataWithRange:NSMakeRange",{"type":20,"tag":64,"props":7783,"children":7784},{"style":93},[7785],{"type":25,"value":96},{"type":20,"tag":64,"props":7787,"children":7788},{"style":142},[7789],{"type":25,"value":2111},{"type":20,"tag":64,"props":7791,"children":7792},{"style":93},[7793],{"type":25,"value":960},{"type":20,"tag":64,"props":7795,"children":7796},{"style":142},[7797],{"type":25,"value":7798},"32",{"type":20,"tag":64,"props":7800,"children":7801},{"style":93},[7802],{"type":25,"value":7803},")];\n",{"type":20,"tag":64,"props":7805,"children":7806},{"class":66,"line":709},[7807],{"type":20,"tag":64,"props":7808,"children":7809},{"emptyLinePlaceholder":703},[7810],{"type":25,"value":706},{"type":20,"tag":64,"props":7812,"children":7813},{"class":66,"line":727},[7814],{"type":20,"tag":64,"props":7815,"children":7816},{"style":2160},[7817],{"type":25,"value":7818},"   // Remove the IV from the encrypted data and decrypt it\n",{"type":20,"tag":64,"props":7820,"children":7821},{"class":66,"line":2407},[7822,7826,7830,7834,7838,7842,7846,7850],{"type":20,"tag":64,"props":7823,"children":7824},{"style":142},[7825],{"type":25,"value":7618},{"type":20,"tag":64,"props":7827,"children":7828},{"style":71},[7829],{"type":25,"value":893},{"type":20,"tag":64,"props":7831,"children":7832},{"style":93},[7833],{"type":25,"value":7627},{"type":20,"tag":64,"props":7835,"children":7836},{"style":71},[7837],{"type":25,"value":1682},{"type":20,"tag":64,"props":7839,"children":7840},{"style":93},[7841],{"type":25,"value":6068},{"type":20,"tag":64,"props":7843,"children":7844},{"style":142},[7845],{"type":25,"value":7640},{"type":20,"tag":64,"props":7847,"children":7848},{"style":142},[7849],{"type":25,"value":7645},{"type":20,"tag":64,"props":7851,"children":7852},{"style":93},[7853],{"type":25,"value":6945},{"type":20,"tag":64,"props":7855,"children":7856},{"class":66,"line":2415},[7857,7861,7866,7870,7874,7878,7882,7886,7891],{"type":20,"tag":64,"props":7858,"children":7859},{"style":93},[7860],{"type":25,"value":7657},{"type":20,"tag":64,"props":7862,"children":7863},{"style":142},[7864],{"type":25,"value":7865},"replaceBytesInRange:NSMakeRange",{"type":20,"tag":64,"props":7867,"children":7868},{"style":93},[7869],{"type":25,"value":96},{"type":20,"tag":64,"props":7871,"children":7872},{"style":142},[7873],{"type":25,"value":2111},{"type":20,"tag":64,"props":7875,"children":7876},{"style":93},[7877],{"type":25,"value":960},{"type":20,"tag":64,"props":7879,"children":7880},{"style":142},[7881],{"type":25,"value":7798},{"type":20,"tag":64,"props":7883,"children":7884},{"style":93},[7885],{"type":25,"value":1741},{"type":20,"tag":64,"props":7887,"children":7888},{"style":142},[7889],{"type":25,"value":7890},"withBytes:NULL",{"type":20,"tag":64,"props":7892,"children":7893},{"style":93},[7894],{"type":25,"value":2147},{"type":20,"tag":64,"props":7896,"children":7897},{"class":66,"line":2424},[7898,7902,7907,7911,7915,7919,7923,7927,7931],{"type":20,"tag":64,"props":7899,"children":7900},{"style":71},[7901],{"type":25,"value":6063},{"type":20,"tag":64,"props":7903,"children":7904},{"style":93},[7905],{"type":25,"value":7906}," [mutableData ",{"type":20,"tag":64,"props":7908,"children":7909},{"style":142},[7910],{"type":25,"value":6653},{"type":20,"tag":64,"props":7912,"children":7913},{"style":93},[7914],{"type":25,"value":2137},{"type":20,"tag":64,"props":7916,"children":7917},{"style":142},[7918],{"type":25,"value":6306},{"type":20,"tag":64,"props":7920,"children":7921},{"style":142},[7922],{"type":25,"value":6311},{"type":20,"tag":64,"props":7924,"children":7925},{"style":93},[7926],{"type":25,"value":2938},{"type":20,"tag":64,"props":7928,"children":7929},{"style":142},[7930],{"type":25,"value":7582},{"type":20,"tag":64,"props":7932,"children":7933},{"style":93},[7934],{"type":25,"value":7587},{"type":20,"tag":64,"props":7936,"children":7937},{"class":66,"line":2432},[7938],{"type":20,"tag":64,"props":7939,"children":7940},{"style":93},[7941],{"type":25,"value":733},{"type":20,"tag":21,"props":7943,"children":7944},{},[7945],{"type":25,"value":7946},"Now, every time an attribute value is saved, its encrypted version includes an extra stage of randomization that prevents comparisons between different attributes encrypted with the same key.",{"type":20,"tag":21,"props":7948,"children":7949},{},[7950],{"type":25,"value":7951},"Thus, with fairly minimal code that ensures resilient encryption, we have an easy way to store private information in Core Data attributes with as many different keys as necessary.",{"type":20,"tag":1519,"props":7953,"children":7954},{},[7955],{"type":25,"value":1523},{"title":8,"searchDepth":123,"depth":123,"links":7957},[7958,7965],{"id":5809,"depth":114,"text":5812,"children":7959},[7960,7961,7962],{"id":5876,"depth":123,"text":5879},{"id":5996,"depth":123,"text":5999},{"id":6709,"depth":123,"text":5879,"children":7963},[7964],{"id":6750,"depth":152,"text":5999},{"id":7267,"depth":114,"text":7270,"children":7966},[7967],{"id":7418,"depth":152,"text":7421},"content:nharrison:2012-07:core-data.md","nharrison/2012-07/core-data.md","nharrison/2012-07/core-data",{"user":7972,"name":7973},"nharrison","Noah Harrison",{"_path":7975,"_dir":5757,"_draft":7,"_partial":7,"_locale":8,"title":7976,"description":7977,"publishDate":7978,"tags":7979,"excerpt":7977,"body":7981,"_type":1529,"_id":8482,"_source":1531,"_file":8483,"_stem":8484,"_extension":1534,"author":8485},"/avogan/2012-07/salt-2","What Your Users Don't Know (Part 2)","In my last post we saw that what your users don't know can hurt them. In other words, how securely you handle your users' private data behind the scenes can have profound implications both for your business and your users' well being. To put it bluntly, it's bad for your business to be publicly shamed over your handling of sensitive data, and it's bad for your users to have their bank accounts pilfered -- those being some of the worse case scenarios.","2012-07-26",[7980,12,13],"cryptography",{"type":17,"children":7982,"toc":8480},[7983,7995,8011,8016,8024,8029,8047,8055,8060,8068,8073,8178,8183,8188,8196,8201,8209,8214,8227,8251,8256,8348,8353,8358,8363,8371,8376,8419,8429,8437,8452,8460,8465,8470,8475],{"type":20,"tag":21,"props":7984,"children":7985},{},[7986,7988,7993],{"type":25,"value":7987},"In my last post we saw that what your users don't know ",{"type":20,"tag":1045,"props":7989,"children":7990},{},[7991],{"type":25,"value":7992},"can",{"type":25,"value":7994}," hurt them. In other words, how securely you handle your users' private data behind the scenes can have profound implications both for your business and your users' well being. To put it bluntly, it's bad for your business to be publicly shamed over your handling of sensitive data, and it's bad for your users to have their bank accounts pilfered -- those being some of the worse case scenarios.",{"type":20,"tag":21,"props":7996,"children":7997},{},[7998],{"type":20,"tag":776,"props":7999,"children":8000},{},[8001,8003,8009],{"type":25,"value":8002},"(This is part 2 of a series on web security; see ",{"type":20,"tag":28,"props":8004,"children":8006},{"href":8005},"/search/user:avogan/what/your/users/don't/know",[8007],{"type":25,"value":8008},"the whole series",{"type":25,"value":8010},").",{"type":20,"tag":21,"props":8012,"children":8013},{},[8014],{"type":25,"value":8015},"So today I'd like to resume our discussion of secure password storage. Let's put our black hat back on, and see what we can break.",{"type":20,"tag":21,"props":8017,"children":8018},{},[8019],{"type":20,"tag":1045,"props":8020,"children":8021},{},[8022],{"type":25,"value":8023},"Bad Assumptions",{"type":20,"tag":21,"props":8025,"children":8026},{},[8027],{"type":25,"value":8028},"I'll start with the easiest case. Sometimes developers assume that as long as their database is safely hidden behind a firewall and an ordinary web server, then it's OK to store everything in plaintext. But this is not true. There are many ways data can leak from your production database, including:",{"type":20,"tag":1862,"props":8030,"children":8031},{},[8032,8037,8042],{"type":20,"tag":1039,"props":8033,"children":8034},{},[8035],{"type":25,"value":8036},"performing a SQL injection attack through your website",{"type":20,"tag":1039,"props":8038,"children":8039},{},[8040],{"type":25,"value":8041},"digging through a backup or archive of your database -- therefore as long as you don't create backups, you're safe*",{"type":20,"tag":1039,"props":8043,"children":8044},{},[8045],{"type":25,"value":8046},"gaining access to the server file system, e.g. through telnet/SSH/RDP",{"type":20,"tag":21,"props":8048,"children":8049},{},[8050],{"type":20,"tag":776,"props":8051,"children":8052},{},[8053],{"type":25,"value":8054},"* That was a joke.",{"type":20,"tag":21,"props":8056,"children":8057},{},[8058],{"type":25,"value":8059},"It is a good rule of thumb that you should design your database with the assumption that malicious users may gain unrestricted access to it at some point. But even if that happens, you should be prepared to breathe a sigh of (slightly nervous) relief, knowing that they still won't be able to use the information maliciously. That doesn't mean you have to encrypt everything, but you should definitely encrypt anything sensitive, such as credit card numbers, passwords, and so on.",{"type":20,"tag":21,"props":8061,"children":8062},{},[8063],{"type":20,"tag":1045,"props":8064,"children":8065},{},[8066],{"type":25,"value":8067},"Naïve Hashing",{"type":20,"tag":21,"props":8069,"children":8070},{},[8071],{"type":25,"value":8072},"A natural first step is to perform a one-way encryption, or \"hash\" on passwords so they are no longer readable in the database. Here's an example:",{"type":20,"tag":8074,"props":8075,"children":8076},"table",{},[8077,8096],{"type":20,"tag":8078,"props":8079,"children":8080},"thead",{},[8081],{"type":20,"tag":8082,"props":8083,"children":8084},"tr",{},[8085,8091],{"type":20,"tag":8086,"props":8087,"children":8088},"th",{},[8089],{"type":25,"value":8090},"UserName",{"type":20,"tag":8086,"props":8092,"children":8093},{},[8094],{"type":25,"value":8095},"PasswordHash",{"type":20,"tag":8097,"props":8098,"children":8099},"tbody",{},[8100,8114,8127,8140,8152,8165],{"type":20,"tag":8082,"props":8101,"children":8102},{},[8103,8109],{"type":20,"tag":8104,"props":8105,"children":8106},"td",{},[8107],{"type":25,"value":8108},"JSmith",{"type":20,"tag":8104,"props":8110,"children":8111},{},[8112],{"type":25,"value":8113},"0xF49A",{"type":20,"tag":8082,"props":8115,"children":8116},{},[8117,8122],{"type":20,"tag":8104,"props":8118,"children":8119},{},[8120],{"type":25,"value":8121},"AJones",{"type":20,"tag":8104,"props":8123,"children":8124},{},[8125],{"type":25,"value":8126},"0x923E",{"type":20,"tag":8082,"props":8128,"children":8129},{},[8130,8135],{"type":20,"tag":8104,"props":8131,"children":8132},{},[8133],{"type":25,"value":8134},"PHensley",{"type":20,"tag":8104,"props":8136,"children":8137},{},[8138],{"type":25,"value":8139},"0x14D0",{"type":20,"tag":8082,"props":8141,"children":8142},{},[8143,8148],{"type":20,"tag":8104,"props":8144,"children":8145},{},[8146],{"type":25,"value":8147},"MRandolph",{"type":20,"tag":8104,"props":8149,"children":8150},{},[8151],{"type":25,"value":8113},{"type":20,"tag":8082,"props":8153,"children":8154},{},[8155,8160],{"type":20,"tag":8104,"props":8156,"children":8157},{},[8158],{"type":25,"value":8159},"DGrove",{"type":20,"tag":8104,"props":8161,"children":8162},{},[8163],{"type":25,"value":8164},"0xE8DB",{"type":20,"tag":8082,"props":8166,"children":8167},{},[8168,8173],{"type":20,"tag":8104,"props":8169,"children":8170},{},[8171],{"type":25,"value":8172},"RSchneider",{"type":20,"tag":8104,"props":8174,"children":8175},{},[8176],{"type":25,"value":8177},"0x551E",{"type":20,"tag":21,"props":8179,"children":8180},{},[8181],{"type":25,"value":8182},"Do you see any problems with the above? OK, ignore the fact that the hashes are very small numbers. This is just pseudo-data for illustration.",{"type":20,"tag":21,"props":8184,"children":8185},{},[8186],{"type":25,"value":8187},"Observant readers will notice that one of the hashes occurs more than once (JSmith and MRandolph). Did you catch that? This is one of the problems with storing password hashes in your database - it's still very easy to see which users chose the same password. Remember, users won't protect themselves, and a surprising number of users may have a password of \"12345\" or \"password\" (or \"Password1\", just to anticipate and refute a well-intentioned, but ultimately insufficient attempt to solve this problem via a more strict password selection process).",{"type":20,"tag":21,"props":8189,"children":8190},{},[8191],{"type":20,"tag":1045,"props":8192,"children":8193},{},[8194],{"type":25,"value":8195},"Beware the Dictionary",{"type":20,"tag":21,"props":8197,"children":8198},{},[8199],{"type":25,"value":8200},"An even deeper problem here is that a hashing scheme like the above is susceptible to a dictionary attack using a large, pre-calculated collection of hashes of common passwords. All it takes is one successful match to positively identify the hashing scheme used, and then start doing damage.",{"type":20,"tag":21,"props":8202,"children":8203},{},[8204],{"type":20,"tag":1045,"props":8205,"children":8206},{},[8207],{"type":25,"value":8208},"Don't Follow This Recipe",{"type":20,"tag":21,"props":8210,"children":8211},{},[8212],{"type":25,"value":8213},"So we have to make sure the hashes we store are unique. We don't want an attacker to be able to recognize any of them. To do this, people use what's called a \"salt\" to make the output more random.",{"type":20,"tag":21,"props":8215,"children":8216},{},[8217],{"type":20,"tag":28,"props":8218,"children":8221},{"href":8219,"rel":8220},"https://artandlogic.com/wp-content/uploads/2012/07/potatohash1.jpg",[32],[8222],{"type":20,"tag":7240,"props":8223,"children":8226},{"alt":8224,"src":8225,"title":8224},"Image of Potato Hash","/avogan/2012-07/img/potatohash.jpg",[],{"type":20,"tag":21,"props":8228,"children":8229},{},[8230,8235,8237],{"type":20,"tag":776,"props":8231,"children":8232},{},[8233],{"type":25,"value":8234},"A well-salted hash.",{"type":25,"value":8236}," ",{"type":20,"tag":776,"props":8238,"children":8239},{},[8240,8241,8249],{"type":25,"value":96},{"type":20,"tag":28,"props":8242,"children":8246},{"href":8243,"rel":8244,"title":8245},"http://www.flickr.com/photos/tavallai/7583913946/in/photostream/",[32],"Flickr photo source",[8247],{"type":25,"value":8248},"photo by Tavallai",{"type":25,"value":8250},", CC BY-ND 2.0)",{"type":20,"tag":21,"props":8252,"children":8253},{},[8254],{"type":25,"value":8255},"The salt is just a random number, and you can combine it with the hash process to get a more random looking output. Here's how one person did that, showing the same data from the table above, but with salt included. Pay special attention to the JSmith and MRandolph records, as before:",{"type":20,"tag":8074,"props":8257,"children":8258},{},[8259,8273],{"type":20,"tag":8078,"props":8260,"children":8261},{},[8262],{"type":20,"tag":8082,"props":8263,"children":8264},{},[8265,8269],{"type":20,"tag":8086,"props":8266,"children":8267},{},[8268],{"type":25,"value":8090},{"type":20,"tag":8086,"props":8270,"children":8271},{},[8272],{"type":25,"value":8095},{"type":20,"tag":8097,"props":8274,"children":8275},{},[8276,8288,8300,8312,8324,8336],{"type":20,"tag":8082,"props":8277,"children":8278},{},[8279,8283],{"type":20,"tag":8104,"props":8280,"children":8281},{},[8282],{"type":25,"value":8108},{"type":20,"tag":8104,"props":8284,"children":8285},{},[8286],{"type":25,"value":8287},"0x832B F49A",{"type":20,"tag":8082,"props":8289,"children":8290},{},[8291,8295],{"type":20,"tag":8104,"props":8292,"children":8293},{},[8294],{"type":25,"value":8121},{"type":20,"tag":8104,"props":8296,"children":8297},{},[8298],{"type":25,"value":8299},"0xDC3C 923E",{"type":20,"tag":8082,"props":8301,"children":8302},{},[8303,8307],{"type":20,"tag":8104,"props":8304,"children":8305},{},[8306],{"type":25,"value":8134},{"type":20,"tag":8104,"props":8308,"children":8309},{},[8310],{"type":25,"value":8311},"0x09A4 14D0",{"type":20,"tag":8082,"props":8313,"children":8314},{},[8315,8319],{"type":20,"tag":8104,"props":8316,"children":8317},{},[8318],{"type":25,"value":8147},{"type":20,"tag":8104,"props":8320,"children":8321},{},[8322],{"type":25,"value":8323},"0xF12E F49A",{"type":20,"tag":8082,"props":8325,"children":8326},{},[8327,8331],{"type":20,"tag":8104,"props":8328,"children":8329},{},[8330],{"type":25,"value":8159},{"type":20,"tag":8104,"props":8332,"children":8333},{},[8334],{"type":25,"value":8335},"0x4C88 E8DB",{"type":20,"tag":8082,"props":8337,"children":8338},{},[8339,8343],{"type":20,"tag":8104,"props":8340,"children":8341},{},[8342],{"type":25,"value":8172},{"type":20,"tag":8104,"props":8344,"children":8345},{},[8346],{"type":25,"value":8347},"0xA4FC 551E",{"type":20,"tag":21,"props":8349,"children":8350},{},[8351],{"type":25,"value":8352},"Whoa, wait a minute. Do you see a new problem here? It is true that each \"PasswordHash\" attribute is now unique since a random number has been prefixed. And the developers may run a few simple SQL queries and verify that no two PasswordHash attributes are the same, and pat themselves on the back. But that is merely a dangerous illusion, and this is a very wrong implementation.",{"type":20,"tag":21,"props":8354,"children":8355},{},[8356],{"type":25,"value":8357},"Since you have your black hat on, it will be obvious to you that a hacker can just bit mask out the part of the hash they are interested in, sort of like performing a Python slice, and exclude the \"salt\" that way. So this erroneous approach has no meaningful improvement over the \"simple hash only\" example above.",{"type":20,"tag":21,"props":8359,"children":8360},{},[8361],{"type":25,"value":8362},"Note: I actually found this erroneous approach used in an online source code recipe, several years ago. Of course it seems absurd to us under this analysis, but somebody thought it was correct enough to post on a source code recipe sharing website, so I think the point was worth belaboring here a bit.",{"type":20,"tag":21,"props":8364,"children":8365},{},[8366],{"type":20,"tag":1045,"props":8367,"children":8368},{},[8369],{"type":25,"value":8370},"A Better Seasoned Recipe",{"type":20,"tag":21,"props":8372,"children":8373},{},[8374],{"type":25,"value":8375},"Here is a more accurate description of how to use salt to protect your password hashes:",{"type":20,"tag":1035,"props":8377,"children":8378},{},[8379,8384,8389,8404,8409,8414],{"type":20,"tag":1039,"props":8380,"children":8381},{},[8382],{"type":25,"value":8383},"In context of creating a new user record or updating a password, receive the plaintext password from the user.",{"type":20,"tag":1039,"props":8385,"children":8386},{},[8387],{"type":25,"value":8388},"Generate a strongly random number to use as the unique salt value for this user record.",{"type":20,"tag":1039,"props":8390,"children":8391},{},[8392,8394,8402],{"type":25,"value":8393},"Compute: a hash of (the salt concatenated with a hash of (the salt concatenated with the password)). Here's ",{"type":20,"tag":28,"props":8395,"children":8399},{"href":8396,"rel":8397,"title":8398},"https://blog.whitehatsec.com/hash-length-extension-attacks/",[32],"Hash length extension attacks",[8400],{"type":25,"value":8401},"a link",{"type":25,"value":8403}," explaining why this expression needs to be this complex, instead of simply a hash of the concatenation.",{"type":20,"tag":1039,"props":8405,"children":8406},{},[8407],{"type":25,"value":8408},"Store both the result of that final hash calculation, and also the unmodified salt value in your database in the user record. I personally like to concatenate the final hash and salt and store them in the same record attribute, just to be obscure. But that doesn't really matter. Note that it's OK to store the salt in plaintext; in fact, that's required.",{"type":20,"tag":1039,"props":8410,"children":8411},{},[8412],{"type":25,"value":8413},"After we are finished with this process, deliberately forget the plaintext password. Depending on the overall architecture, maybe it is was provided by the user, or maybe it was system-generated and must now be emailed to the user. Either way, it must not be stored as plaintext.",{"type":20,"tag":1039,"props":8415,"children":8416},{},[8417],{"type":25,"value":8418},"Later on, when the user enters their user name and password to log in, look up the record by user name, then repeat the calculation in step 3 using the salt value retrieved from the record. The resulting hash (using the password being entered) can be checked against the stored hash from the database to determine if the user entered the right password.",{"type":20,"tag":21,"props":8420,"children":8421},{},[8422,8424],{"type":25,"value":8423},"If you do it right, your database's hashes should now look totally scrambled and inscrutable to an unauthorized reader.  ",{"type":20,"tag":776,"props":8425,"children":8426},{},[8427],{"type":25,"value":8428},"(Reminder to self: next time must avoid blogging while hungry, especially about recipes for salted hashes and ordering crackable things as scrambled.)",{"type":20,"tag":21,"props":8430,"children":8431},{},[8432],{"type":20,"tag":1045,"props":8433,"children":8434},{},[8435],{"type":25,"value":8436},"Choosing a Hash Function",{"type":20,"tag":21,"props":8438,"children":8439},{},[8440,8442,8450],{"type":25,"value":8441},"This blog post is not a complete treatment of the subject of server side salting and password hashing. Another important decision is what hashing function to use. A hash function in this context is typically chosen to be both secure and slow. But it's also a moving target, as cryptographic standards must continually respond to rapidly advancing cracking capabilities. Somehow the very weak MD5 ended up as an entrenched hash function in very widespread use in the 90's and aughts. (Boy, was that a short sighted mistake.) Many people are still using SHA-1, which wasn't considered horrible just a few years ago, but really needs to be deprecated in favor of stronger options. I recommend you spend some time reading the links in ",{"type":20,"tag":28,"props":8443,"children":8447},{"href":8444,"rel":8445,"title":8446},"http://stackoverflow.com/questions/2549988/whats-the-recommended-hashing-algorithm-to-use-for-stored-passwords",[32],"Stack Overflow discussion of what hash function to choose",[8448],{"type":25,"value":8449},"this discussion",{"type":25,"value":8451}," to get a sense of what's out there. I'm deliberately not giving a specific recommendation here, in order to reinforce that there is actually more than one possible answer, and also that the \"correct answers\" periodically change.",{"type":20,"tag":21,"props":8453,"children":8454},{},[8455],{"type":20,"tag":1045,"props":8456,"children":8457},{},[8458],{"type":25,"value":8459},"Don't Try This At Home",{"type":20,"tag":21,"props":8461,"children":8462},{},[8463],{"type":25,"value":8464},"My final advice may sound like it contradicts everything I've said thus far. But that's OK. :)",{"type":20,"tag":21,"props":8466,"children":8467},{},[8468],{"type":25,"value":8469},"If at all possible, you should not come up with your own implementation of these approaches. Ideally, you should rely on your framework libraries to provide high level, complete authentication and authorization wrappers. Or if not, at least you should find and integrate a secure implementation from a trusted source. I already showed you how some guy on the internet thought they were salting their passwords, but got it totally wrong; so definitely don't trust random stuff you google up.",{"type":20,"tag":21,"props":8471,"children":8472},{},[8473],{"type":25,"value":8474},"Be very cautious if you're not a cryptographic expert. Certainly, you can and should learn the basics of information security, and use your knowledge to audit and critique your own systems. But any implementations you deploy to production should be from trusted frameworks, or at least closely follow standard industry best practices. Don't assemble something off the top of your head, or it will almost certainly be cryptographically weak and defective.",{"type":20,"tag":21,"props":8476,"children":8477},{},[8478],{"type":25,"value":8479},"Thanks for reading! You can take the black hat off now. Hopefully this was informative for somebody; if you have any questions or want to share your own advice for readers, I'd love to read your comments below.",{"title":8,"searchDepth":123,"depth":123,"links":8481},[],"content:avogan:2012-07:salt-2.md","avogan/2012-07/salt-2.md","avogan/2012-07/salt-2",{"user":8486,"name":8487},"avogan","Andrew Vogan",{"_path":8489,"_dir":5757,"_draft":7,"_partial":7,"_locale":8,"title":8490,"description":8491,"publishDate":8492,"tags":8493,"excerpt":8491,"body":8494,"_type":1529,"_id":8845,"_source":1531,"_file":8846,"_stem":8847,"_extension":1534,"author":8848},"/avogan/2012-07/salt","What Your Users Don't Know (Part 1)","What's wrong with this code?","2012-07-13",[7980,12,13],{"type":17,"children":8495,"toc":8843},[8496,8500,8513,8683,8698,8721,8728,8743,8755,8761,8766,8772,8814,8820,8834,8839],{"type":20,"tag":21,"props":8497,"children":8498},{},[8499],{"type":25,"value":8491},{"type":20,"tag":21,"props":8501,"children":8502},{},[8503],{"type":20,"tag":776,"props":8504,"children":8505},{},[8506,8508,8512],{"type":25,"value":8507},"(This is part 1 of a series on web security; see ",{"type":20,"tag":28,"props":8509,"children":8510},{"href":8005},[8511],{"type":25,"value":8008},{"type":25,"value":8010},{"type":20,"tag":53,"props":8514,"children":8516},{"className":55,"code":8515,"language":57,"meta":8,"style":8},"bool IsValidUser(string userName, string password)\n{\n   string sql = string.Format(\"SELECT 1 FROM person \" + \n                              \"WHERE userName = '{0}' AND password = '{1}'\",\n                              userName,\n                              password);\n   return ExecuteQuery(sql).Rows > 0;\n}\n",[8517],{"type":20,"tag":60,"props":8518,"children":8519},{"__ignoreMap":8},[8520,8563,8570,8619,8631,8639,8647,8676],{"type":20,"tag":64,"props":8521,"children":8522},{"class":66,"line":67},[8523,8528,8533,8537,8541,8546,8550,8554,8559],{"type":20,"tag":64,"props":8524,"children":8525},{"style":71},[8526],{"type":25,"value":8527},"bool",{"type":20,"tag":64,"props":8529,"children":8530},{"style":87},[8531],{"type":25,"value":8532}," IsValidUser",{"type":20,"tag":64,"props":8534,"children":8535},{"style":93},[8536],{"type":25,"value":96},{"type":20,"tag":64,"props":8538,"children":8539},{"style":71},[8540],{"type":25,"value":1153},{"type":20,"tag":64,"props":8542,"children":8543},{"style":87},[8544],{"type":25,"value":8545}," userName",{"type":20,"tag":64,"props":8547,"children":8548},{"style":93},[8549],{"type":25,"value":960},{"type":20,"tag":64,"props":8551,"children":8552},{"style":71},[8553],{"type":25,"value":1153},{"type":20,"tag":64,"props":8555,"children":8556},{"style":87},[8557],{"type":25,"value":8558}," password",{"type":20,"tag":64,"props":8560,"children":8561},{"style":93},[8562],{"type":25,"value":111},{"type":20,"tag":64,"props":8564,"children":8565},{"class":66,"line":114},[8566],{"type":20,"tag":64,"props":8567,"children":8568},{"style":93},[8569],{"type":25,"value":120},{"type":20,"tag":64,"props":8571,"children":8572},{"class":66,"line":123},[8573,8578,8583,8587,8591,8595,8600,8604,8609,8614],{"type":20,"tag":64,"props":8574,"children":8575},{"style":71},[8576],{"type":25,"value":8577},"   string",{"type":20,"tag":64,"props":8579,"children":8580},{"style":87},[8581],{"type":25,"value":8582}," sql",{"type":20,"tag":64,"props":8584,"children":8585},{"style":71},[8586],{"type":25,"value":863},{"type":20,"tag":64,"props":8588,"children":8589},{"style":71},[8590],{"type":25,"value":84},{"type":20,"tag":64,"props":8592,"children":8593},{"style":93},[8594],{"type":25,"value":1569},{"type":20,"tag":64,"props":8596,"children":8597},{"style":87},[8598],{"type":25,"value":8599},"Format",{"type":20,"tag":64,"props":8601,"children":8602},{"style":93},[8603],{"type":25,"value":96},{"type":20,"tag":64,"props":8605,"children":8606},{"style":161},[8607],{"type":25,"value":8608},"\"SELECT 1 FROM person \"",{"type":20,"tag":64,"props":8610,"children":8611},{"style":71},[8612],{"type":25,"value":8613}," +",{"type":20,"tag":64,"props":8615,"children":8616},{"style":93},[8617],{"type":25,"value":8618}," \n",{"type":20,"tag":64,"props":8620,"children":8621},{"class":66,"line":152},[8622,8627],{"type":20,"tag":64,"props":8623,"children":8624},{"style":161},[8625],{"type":25,"value":8626},"                              \"WHERE userName = '{0}' AND password = '{1}'\"",{"type":20,"tag":64,"props":8628,"children":8629},{"style":93},[8630],{"type":25,"value":1219},{"type":20,"tag":64,"props":8632,"children":8633},{"class":66,"line":172},[8634],{"type":20,"tag":64,"props":8635,"children":8636},{"style":93},[8637],{"type":25,"value":8638},"                              userName,\n",{"type":20,"tag":64,"props":8640,"children":8641},{"class":66,"line":218},[8642],{"type":20,"tag":64,"props":8643,"children":8644},{"style":93},[8645],{"type":25,"value":8646},"                              password);\n",{"type":20,"tag":64,"props":8648,"children":8649},{"class":66,"line":235},[8650,8654,8659,8664,8668,8672],{"type":20,"tag":64,"props":8651,"children":8652},{"style":71},[8653],{"type":25,"value":6063},{"type":20,"tag":64,"props":8655,"children":8656},{"style":87},[8657],{"type":25,"value":8658}," ExecuteQuery",{"type":20,"tag":64,"props":8660,"children":8661},{"style":93},[8662],{"type":25,"value":8663},"(sql).Rows ",{"type":20,"tag":64,"props":8665,"children":8666},{"style":71},[8667],{"type":25,"value":186},{"type":20,"tag":64,"props":8669,"children":8670},{"style":142},[8671],{"type":25,"value":145},{"type":20,"tag":64,"props":8673,"children":8674},{"style":93},[8675],{"type":25,"value":169},{"type":20,"tag":64,"props":8677,"children":8678},{"class":66,"line":276},[8679],{"type":20,"tag":64,"props":8680,"children":8681},{"style":93},[8682],{"type":25,"value":733},{"type":20,"tag":21,"props":8684,"children":8685},{},[8686,8688,8696],{"type":25,"value":8687},"Any jokester who says \"it looks fine to me\" will be sent to the ",{"type":20,"tag":28,"props":8689,"children":8693},{"href":8690,"rel":8691,"title":8692},"http://starwars.wikia.com/wiki/Spice_Mines_of_Kessel",[32],"Spice Mines of Kessel",[8694],{"type":25,"value":8695},"spice mines of Kessel",{"type":25,"value":8697},". But I think for observant readers, a couple of critical security errors will practically jump off the screen:",{"type":20,"tag":1862,"props":8699,"children":8700},{},[8701,8716],{"type":20,"tag":1039,"props":8702,"children":8703},{},[8704,8706,8714],{"type":25,"value":8705},"User inputs are being concatenated directly into a SQL query string, risking a ",{"type":20,"tag":28,"props":8707,"children":8711},{"href":8708,"rel":8709,"title":8710},"http://en.wikipedia.org/wiki/SQL_injection",[32],"SQL Injection Attack",[8712],{"type":25,"value":8713},"SQL injection",{"type":25,"value":8715}," attack.",{"type":20,"tag":1039,"props":8717,"children":8718},{},[8719],{"type":25,"value":8720},"Passwords are stored in plaintext, exposing users to further harm in the event the database is accessed.",{"type":20,"tag":8722,"props":8723,"children":8725},"h1",{"id":8724},"in-the-real-world",[8726],{"type":25,"value":8727},"In the Real World",{"type":20,"tag":21,"props":8729,"children":8730},{},[8731,8733,8741],{"type":25,"value":8732},"If you keep up with the news, you may have seen that no less an internet giant than Yahoo may have been guilty of both of the above mistakes, leading to ",{"type":20,"tag":28,"props":8734,"children":8738},{"href":8735,"rel":8736,"title":8737},"http://arstechnica.com/security/2012/07/yahoo-service-hacked/",[32],"Yahoo security breach",[8739],{"type":25,"value":8740},"a breach of 435K user credentials",{"type":25,"value":8742},". This is a disaster for any company that safeguards private user data.",{"type":20,"tag":21,"props":8744,"children":8745},{},[8746,8748,8753],{"type":25,"value":8747},"You can't depend on users to protect themselves; somewhere out in the world today is a person who set up the same password on a Justin Bieber mailing list website and also their online banking. So if even a fluffy, non-important website drops the ball, users may see their bank accounts emptied. That's probably an extreme worst case, though there is a whole range of other mischief you don't want to enable either. The point is, ",{"type":20,"tag":1045,"props":8749,"children":8750},{},[8751],{"type":25,"value":8752},"your users trust you, and they don't know what you are doing with their data.",{"type":25,"value":8754}," Be worthy of their trust.",{"type":20,"tag":8722,"props":8756,"children":8758},{"id":8757},"get-in-the-mindset",[8759],{"type":25,"value":8760},"Get In the Mindset",{"type":20,"tag":21,"props":8762,"children":8763},{},[8764],{"type":25,"value":8765},"A technique I find helpful for programmers is to temporarily put down their shining knight helmet and try on a black hat for size. Put yourself in a creative trouble-maker frame of mind. Ask the question: how could somebody compromise my website and harm my users or my organization?",{"type":20,"tag":8722,"props":8767,"children":8769},{"id":8768},"sql-injection",[8770],{"type":25,"value":8771},"SQL Injection",{"type":20,"tag":21,"props":8773,"children":8774},{},[8775,8777,8785,8787,8795,8796,8803,8805,8812],{"type":25,"value":8776},"In the case of the code snippet at the top of this article, it is trivially easy for a hacker to enter a user name or password that will disrupt the query. By placing complex SQL expressions (perhaps cleverly including SQL comments) in the user name and password inputs, you can easily ",{"type":20,"tag":28,"props":8778,"children":8782},{"href":8779,"rel":8780,"title":8781},"http://xkcd.com/327/",[32],"Little Bobby Tables",[8783],{"type":25,"value":8784},"delete or insert",{"type":25,"value":8786}," records. What would totally frustrate your hacking attempts, though, is if the programmer used their framework's feature for formal query value parameters (see for ",{"type":20,"tag":28,"props":8788,"children":8792},{"href":8789,"rel":8790,"title":8791},"http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlcommand.parameters.aspx",[32],"framework query params",[8793],{"type":25,"value":8794},"C#",{"type":25,"value":960},{"type":20,"tag":28,"props":8797,"children":8800},{"href":8798,"rel":8799,"title":8791},"http://stackoverflow.com/questions/3410455/how-do-i-use-sql-parameters-with-python",[32],[8801],{"type":25,"value":8802},"Python",{"type":25,"value":8804},", etc). And that, of course, is the correct answer here. Never concatenate user inputs into SQL strings. It's even a bad idea to write your own sanitizing functions, because you'll probably get a detail wrong, even if you're a smart person. Just use the framework, all the time, or else use a mainstream ",{"type":20,"tag":28,"props":8806,"children":8810},{"href":8807,"rel":8808,"title":8809},"http://en.wikipedia.org/wiki/Object-relational_mapping",[32],"ORM",[8811],{"type":25,"value":8809},{"type":25,"value":8813}," that hides the query string safely out of your code's sight.",{"type":20,"tag":8722,"props":8815,"children":8817},{"id":8816},"plaintext-passwords",[8818],{"type":25,"value":8819},"Plaintext Passwords",{"type":20,"tag":21,"props":8821,"children":8822},{},[8823,8825,8832],{"type":25,"value":8824},"The other major problem is the use of plaintext password storage. That's obviously a really bad thing if the database is accessed, and many programmers are aware that if you just do a one-way hash of the password, it's more secure. You do lose the ability to remind the user of their password, but it's usually OK, because they can just create a new one when needed via an email challenge/response. But even hashing itself doesn't cut it. If you are not ",{"type":20,"tag":28,"props":8826,"children":8830},{"href":8827,"rel":8828,"title":8829},"http://en.wikipedia.org/wiki/Salt_(cryptography)",[32],"salting",[8831],{"type":25,"value":8829},{"type":25,"value":8833}," your password hashes, your users are exposed to unacceptable risk.",{"type":20,"tag":21,"props":8835,"children":8836},{},[8837],{"type":25,"value":8838},"I'll take a closer look at how to salt passwords in a future post. It really sounds more difficult than it is. So to summarize: do some reading, and also occasionally just put yourself in a black hat frame of mind, and you can work out how to close common loopholes.",{"type":20,"tag":1519,"props":8840,"children":8841},{},[8842],{"type":25,"value":1523},{"title":8,"searchDepth":123,"depth":123,"links":8844},[],"content:avogan:2012-07:salt.md","avogan/2012-07/salt.md","avogan/2012-07/salt",{"user":8486,"name":8487},1780330267730]