Autogenerated HTML docs for v2.48.1-157-g3b0d05
[git-htmldocs.git] / howto / recover-corrupted-object-harder.html
blob8f88410dfd055c43b4c04fc27ac5342a19702022
1 <!DOCTYPE html>
2 <html xmlns="http://www.w3.org/1999/xhtml" lang="en">
3 <head>
4 <meta charset="UTF-8"/>
5 <meta http-equiv="X-UA-Compatible" content="IE=edge"/>
6 <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
7 <meta name="generator" content="Asciidoctor 2.0.20"/>
8 <title>How to recover an object from scratch</title>
9 <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700"/>
10 <style>
11 /*! Asciidoctor default stylesheet | MIT License | https://asciidoctor.org */
12 /* Uncomment the following line when using as a custom stylesheet */
13 /* @import "https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700"; */
14 html{font-family:sans-serif;-webkit-text-size-adjust:100%}
15 a{background:none}
16 a:focus{outline:thin dotted}
17 a:active,a:hover{outline:0}
18 h1{font-size:2em;margin:.67em 0}
19 b,strong{font-weight:bold}
20 abbr{font-size:.9em}
21 abbr[title]{cursor:help;border-bottom:1px dotted #dddddf;text-decoration:none}
22 dfn{font-style:italic}
23 hr{height:0}
24 mark{background:#ff0;color:#000}
25 code,kbd,pre,samp{font-family:monospace;font-size:1em}
26 pre{white-space:pre-wrap}
27 q{quotes:"\201C" "\201D" "\2018" "\2019"}
28 small{font-size:80%}
29 sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}
30 sup{top:-.5em}
31 sub{bottom:-.25em}
32 img{border:0}
33 svg:not(:root){overflow:hidden}
34 figure{margin:0}
35 audio,video{display:inline-block}
36 audio:not([controls]){display:none;height:0}
37 fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}
38 legend{border:0;padding:0}
39 button,input,select,textarea{font-family:inherit;font-size:100%;margin:0}
40 button,input{line-height:normal}
41 button,select{text-transform:none}
42 button,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}
43 button[disabled],html input[disabled]{cursor:default}
44 input[type=checkbox],input[type=radio]{padding:0}
45 button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}
46 textarea{overflow:auto;vertical-align:top}
47 table{border-collapse:collapse;border-spacing:0}
48 *,::before,::after{box-sizing:border-box}
49 html,body{font-size:100%}
50 body{background:#fff;color:rgba(0,0,0,.8);padding:0;margin:0;font-family:"Noto Serif","DejaVu Serif",serif;line-height:1;position:relative;cursor:auto;-moz-tab-size:4;-o-tab-size:4;tab-size:4;word-wrap:anywhere;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased}
51 a:hover{cursor:pointer}
52 img,object,embed{max-width:100%;height:auto}
53 object,embed{height:100%}
54 img{-ms-interpolation-mode:bicubic}
55 .left{float:left!important}
56 .right{float:right!important}
57 .text-left{text-align:left!important}
58 .text-right{text-align:right!important}
59 .text-center{text-align:center!important}
60 .text-justify{text-align:justify!important}
61 .hide{display:none}
62 img,object,svg{display:inline-block;vertical-align:middle}
63 textarea{height:auto;min-height:50px}
64 select{width:100%}
65 .subheader,.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{line-height:1.45;color:#7a2518;font-weight:400;margin-top:0;margin-bottom:.25em}
66 div,dl,dt,dd,ul,ol,li,h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6,pre,form,p,blockquote,th,td{margin:0;padding:0}
67 a{color:#2156a5;text-decoration:underline;line-height:inherit}
68 a:hover,a:focus{color:#1d4b8f}
69 a img{border:0}
70 p{line-height:1.6;margin-bottom:1.25em;text-rendering:optimizeLegibility}
71 p aside{font-size:.875em;line-height:1.35;font-style:italic}
72 h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{font-family:"Open Sans","DejaVu Sans",sans-serif;font-weight:300;font-style:normal;color:#ba3925;text-rendering:optimizeLegibility;margin-top:1em;margin-bottom:.5em;line-height:1.0125em}
73 h1 small,h2 small,h3 small,#toctitle small,.sidebarblock>.content>.title small,h4 small,h5 small,h6 small{font-size:60%;color:#e99b8f;line-height:0}
74 h1{font-size:2.125em}
75 h2{font-size:1.6875em}
76 h3,#toctitle,.sidebarblock>.content>.title{font-size:1.375em}
77 h4,h5{font-size:1.125em}
78 h6{font-size:1em}
79 hr{border:solid #dddddf;border-width:1px 0 0;clear:both;margin:1.25em 0 1.1875em}
80 em,i{font-style:italic;line-height:inherit}
81 strong,b{font-weight:bold;line-height:inherit}
82 small{font-size:60%;line-height:inherit}
83 code{font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;font-weight:400;color:rgba(0,0,0,.9)}
84 ul,ol,dl{line-height:1.6;margin-bottom:1.25em;list-style-position:outside;font-family:inherit}
85 ul,ol{margin-left:1.5em}
86 ul li ul,ul li ol{margin-left:1.25em;margin-bottom:0}
87 ul.circle{list-style-type:circle}
88 ul.disc{list-style-type:disc}
89 ul.square{list-style-type:square}
90 ul.circle ul:not([class]),ul.disc ul:not([class]),ul.square ul:not([class]){list-style:inherit}
91 ol li ul,ol li ol{margin-left:1.25em;margin-bottom:0}
92 dl dt{margin-bottom:.3125em;font-weight:bold}
93 dl dd{margin-bottom:1.25em}
94 blockquote{margin:0 0 1.25em;padding:.5625em 1.25em 0 1.1875em;border-left:1px solid #ddd}
95 blockquote,blockquote p{line-height:1.6;color:rgba(0,0,0,.85)}
96 @media screen and (min-width:768px){h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2}
97 h1{font-size:2.75em}
98 h2{font-size:2.3125em}
99 h3,#toctitle,.sidebarblock>.content>.title{font-size:1.6875em}
100 h4{font-size:1.4375em}}
101 table{background:#fff;margin-bottom:1.25em;border:1px solid #dedede;word-wrap:normal}
102 table thead,table tfoot{background:#f7f8f7}
103 table thead tr th,table thead tr td,table tfoot tr th,table tfoot tr td{padding:.5em .625em .625em;font-size:inherit;color:rgba(0,0,0,.8);text-align:left}
104 table tr th,table tr td{padding:.5625em .625em;font-size:inherit;color:rgba(0,0,0,.8)}
105 table tr.even,table tr.alt{background:#f8f8f7}
106 table thead tr th,table tfoot tr th,table tbody tr td,table tr td,table tfoot tr td{line-height:1.6}
107 h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2;word-spacing:-.05em}
108 h1 strong,h2 strong,h3 strong,#toctitle strong,.sidebarblock>.content>.title strong,h4 strong,h5 strong,h6 strong{font-weight:400}
109 .center{margin-left:auto;margin-right:auto}
110 .stretch{width:100%}
111 .clearfix::before,.clearfix::after,.float-group::before,.float-group::after{content:" ";display:table}
112 .clearfix::after,.float-group::after{clear:both}
113 :not(pre).nobreak{word-wrap:normal}
114 :not(pre).nowrap{white-space:nowrap}
115 :not(pre).pre-wrap{white-space:pre-wrap}
116 :not(pre):not([class^=L])>code{font-size:.9375em;font-style:normal!important;letter-spacing:0;padding:.1em .5ex;word-spacing:-.15em;background:#f7f7f8;border-radius:4px;line-height:1.45;text-rendering:optimizeSpeed}
117 pre{color:rgba(0,0,0,.9);font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;line-height:1.45;text-rendering:optimizeSpeed}
118 pre code,pre pre{color:inherit;font-size:inherit;line-height:inherit}
119 pre>code{display:block}
120 pre.nowrap,pre.nowrap pre{white-space:pre;word-wrap:normal}
121 em em{font-style:normal}
122 strong strong{font-weight:400}
123 .keyseq{color:rgba(51,51,51,.8)}
124 kbd{font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;display:inline-block;color:rgba(0,0,0,.8);font-size:.65em;line-height:1.45;background:#f7f7f7;border:1px solid #ccc;border-radius:3px;box-shadow:0 1px 0 rgba(0,0,0,.2),inset 0 0 0 .1em #fff;margin:0 .15em;padding:.2em .5em;vertical-align:middle;position:relative;top:-.1em;white-space:nowrap}
125 .keyseq kbd:first-child{margin-left:0}
126 .keyseq kbd:last-child{margin-right:0}
127 .menuseq,.menuref{color:#000}
128 .menuseq b:not(.caret),.menuref{font-weight:inherit}
129 .menuseq{word-spacing:-.02em}
130 .menuseq b.caret{font-size:1.25em;line-height:.8}
131 .menuseq i.caret{font-weight:bold;text-align:center;width:.45em}
132 b.button::before,b.button::after{position:relative;top:-1px;font-weight:400}
133 b.button::before{content:"[";padding:0 3px 0 2px}
134 b.button::after{content:"]";padding:0 2px 0 3px}
135 p a>code:hover{color:rgba(0,0,0,.9)}
136 #header,#content,#footnotes,#footer{width:100%;margin:0 auto;max-width:62.5em;*zoom:1;position:relative;padding-left:.9375em;padding-right:.9375em}
137 #header::before,#header::after,#content::before,#content::after,#footnotes::before,#footnotes::after,#footer::before,#footer::after{content:" ";display:table}
138 #header::after,#content::after,#footnotes::after,#footer::after{clear:both}
139 #content{margin-top:1.25em}
140 #content::before{content:none}
141 #header>h1:first-child{color:rgba(0,0,0,.85);margin-top:2.25rem;margin-bottom:0}
142 #header>h1:first-child+#toc{margin-top:8px;border-top:1px solid #dddddf}
143 #header>h1:only-child,body.toc2 #header>h1:nth-last-child(2){border-bottom:1px solid #dddddf;padding-bottom:8px}
144 #header .details{border-bottom:1px solid #dddddf;line-height:1.45;padding-top:.25em;padding-bottom:.25em;padding-left:.25em;color:rgba(0,0,0,.6);display:flex;flex-flow:row wrap}
145 #header .details span:first-child{margin-left:-.125em}
146 #header .details span.email a{color:rgba(0,0,0,.85)}
147 #header .details br{display:none}
148 #header .details br+span::before{content:"\00a0\2013\00a0"}
149 #header .details br+span.author::before{content:"\00a0\22c5\00a0";color:rgba(0,0,0,.85)}
150 #header .details br+span#revremark::before{content:"\00a0|\00a0"}
151 #header #revnumber{text-transform:capitalize}
152 #header #revnumber::after{content:"\00a0"}
153 #content>h1:first-child:not([class]){color:rgba(0,0,0,.85);border-bottom:1px solid #dddddf;padding-bottom:8px;margin-top:0;padding-top:1rem;margin-bottom:1.25rem}
154 #toc{border-bottom:1px solid #e7e7e9;padding-bottom:.5em}
155 #toc>ul{margin-left:.125em}
156 #toc ul.sectlevel0>li>a{font-style:italic}
157 #toc ul.sectlevel0 ul.sectlevel1{margin:.5em 0}
158 #toc ul{font-family:"Open Sans","DejaVu Sans",sans-serif;list-style-type:none}
159 #toc li{line-height:1.3334;margin-top:.3334em}
160 #toc a{text-decoration:none}
161 #toc a:active{text-decoration:underline}
162 #toctitle{color:#7a2518;font-size:1.2em}
163 @media screen and (min-width:768px){#toctitle{font-size:1.375em}
164 body.toc2{padding-left:15em;padding-right:0}
165 #toc.toc2{margin-top:0!important;background:#f8f8f7;position:fixed;width:15em;left:0;top:0;border-right:1px solid #e7e7e9;border-top-width:0!important;border-bottom-width:0!important;z-index:1000;padding:1.25em 1em;height:100%;overflow:auto}
166 #toc.toc2 #toctitle{margin-top:0;margin-bottom:.8rem;font-size:1.2em}
167 #toc.toc2>ul{font-size:.9em;margin-bottom:0}
168 #toc.toc2 ul ul{margin-left:0;padding-left:1em}
169 #toc.toc2 ul.sectlevel0 ul.sectlevel1{padding-left:0;margin-top:.5em;margin-bottom:.5em}
170 body.toc2.toc-right{padding-left:0;padding-right:15em}
171 body.toc2.toc-right #toc.toc2{border-right-width:0;border-left:1px solid #e7e7e9;left:auto;right:0}}
172 @media screen and (min-width:1280px){body.toc2{padding-left:20em;padding-right:0}
173 #toc.toc2{width:20em}
174 #toc.toc2 #toctitle{font-size:1.375em}
175 #toc.toc2>ul{font-size:.95em}
176 #toc.toc2 ul ul{padding-left:1.25em}
177 body.toc2.toc-right{padding-left:0;padding-right:20em}}
178 #content #toc{border:1px solid #e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;border-radius:4px}
179 #content #toc>:first-child{margin-top:0}
180 #content #toc>:last-child{margin-bottom:0}
181 #footer{max-width:none;background:rgba(0,0,0,.8);padding:1.25em}
182 #footer-text{color:hsla(0,0%,100%,.8);line-height:1.44}
183 #content{margin-bottom:.625em}
184 .sect1{padding-bottom:.625em}
185 @media screen and (min-width:768px){#content{margin-bottom:1.25em}
186 .sect1{padding-bottom:1.25em}}
187 .sect1:last-child{padding-bottom:0}
188 .sect1+.sect1{border-top:1px solid #e7e7e9}
189 #content h1>a.anchor,h2>a.anchor,h3>a.anchor,#toctitle>a.anchor,.sidebarblock>.content>.title>a.anchor,h4>a.anchor,h5>a.anchor,h6>a.anchor{position:absolute;z-index:1001;width:1.5ex;margin-left:-1.5ex;display:block;text-decoration:none!important;visibility:hidden;text-align:center;font-weight:400}
190 #content h1>a.anchor::before,h2>a.anchor::before,h3>a.anchor::before,#toctitle>a.anchor::before,.sidebarblock>.content>.title>a.anchor::before,h4>a.anchor::before,h5>a.anchor::before,h6>a.anchor::before{content:"\00A7";font-size:.85em;display:block;padding-top:.1em}
191 #content h1:hover>a.anchor,#content h1>a.anchor:hover,h2:hover>a.anchor,h2>a.anchor:hover,h3:hover>a.anchor,#toctitle:hover>a.anchor,.sidebarblock>.content>.title:hover>a.anchor,h3>a.anchor:hover,#toctitle>a.anchor:hover,.sidebarblock>.content>.title>a.anchor:hover,h4:hover>a.anchor,h4>a.anchor:hover,h5:hover>a.anchor,h5>a.anchor:hover,h6:hover>a.anchor,h6>a.anchor:hover{visibility:visible}
192 #content h1>a.link,h2>a.link,h3>a.link,#toctitle>a.link,.sidebarblock>.content>.title>a.link,h4>a.link,h5>a.link,h6>a.link{color:#ba3925;text-decoration:none}
193 #content h1>a.link:hover,h2>a.link:hover,h3>a.link:hover,#toctitle>a.link:hover,.sidebarblock>.content>.title>a.link:hover,h4>a.link:hover,h5>a.link:hover,h6>a.link:hover{color:#a53221}
194 details,.audioblock,.imageblock,.literalblock,.listingblock,.stemblock,.videoblock{margin-bottom:1.25em}
195 details{margin-left:1.25rem}
196 details>summary{cursor:pointer;display:block;position:relative;line-height:1.6;margin-bottom:.625rem;outline:none;-webkit-tap-highlight-color:transparent}
197 details>summary::-webkit-details-marker{display:none}
198 details>summary::before{content:"";border:solid transparent;border-left:solid;border-width:.3em 0 .3em .5em;position:absolute;top:.5em;left:-1.25rem;transform:translateX(15%)}
199 details[open]>summary::before{border:solid transparent;border-top:solid;border-width:.5em .3em 0;transform:translateY(15%)}
200 details>summary::after{content:"";width:1.25rem;height:1em;position:absolute;top:.3em;left:-1.25rem}
201 .admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{text-rendering:optimizeLegibility;text-align:left;font-family:"Noto Serif","DejaVu Serif",serif;font-size:1rem;font-style:italic}
202 table.tableblock.fit-content>caption.title{white-space:nowrap;width:0}
203 .paragraph.lead>p,#preamble>.sectionbody>[class=paragraph]:first-of-type p{font-size:1.21875em;line-height:1.6;color:rgba(0,0,0,.85)}
204 .admonitionblock>table{border-collapse:separate;border:0;background:none;width:100%}
205 .admonitionblock>table td.icon{text-align:center;width:80px}
206 .admonitionblock>table td.icon img{max-width:none}
207 .admonitionblock>table td.icon .title{font-weight:bold;font-family:"Open Sans","DejaVu Sans",sans-serif;text-transform:uppercase}
208 .admonitionblock>table td.content{padding-left:1.125em;padding-right:1.25em;border-left:1px solid #dddddf;color:rgba(0,0,0,.6);word-wrap:anywhere}
209 .admonitionblock>table td.content>:last-child>:last-child{margin-bottom:0}
210 .exampleblock>.content{border:1px solid #e6e6e6;margin-bottom:1.25em;padding:1.25em;background:#fff;border-radius:4px}
211 .sidebarblock{border:1px solid #dbdbd6;margin-bottom:1.25em;padding:1.25em;background:#f3f3f2;border-radius:4px}
212 .sidebarblock>.content>.title{color:#7a2518;margin-top:0;text-align:center}
213 .exampleblock>.content>:first-child,.sidebarblock>.content>:first-child{margin-top:0}
214 .exampleblock>.content>:last-child,.exampleblock>.content>:last-child>:last-child,.exampleblock>.content .olist>ol>li:last-child>:last-child,.exampleblock>.content .ulist>ul>li:last-child>:last-child,.exampleblock>.content .qlist>ol>li:last-child>:last-child,.sidebarblock>.content>:last-child,.sidebarblock>.content>:last-child>:last-child,.sidebarblock>.content .olist>ol>li:last-child>:last-child,.sidebarblock>.content .ulist>ul>li:last-child>:last-child,.sidebarblock>.content .qlist>ol>li:last-child>:last-child{margin-bottom:0}
215 .literalblock pre,.listingblock>.content>pre{border-radius:4px;overflow-x:auto;padding:1em;font-size:.8125em}
216 @media screen and (min-width:768px){.literalblock pre,.listingblock>.content>pre{font-size:.90625em}}
217 @media screen and (min-width:1280px){.literalblock pre,.listingblock>.content>pre{font-size:1em}}
218 .literalblock pre,.listingblock>.content>pre:not(.highlight),.listingblock>.content>pre[class=highlight],.listingblock>.content>pre[class^="highlight "]{background:#f7f7f8}
219 .literalblock.output pre{color:#f7f7f8;background:rgba(0,0,0,.9)}
220 .listingblock>.content{position:relative}
221 .listingblock code[data-lang]::before{display:none;content:attr(data-lang);position:absolute;font-size:.75em;top:.425rem;right:.5rem;line-height:1;text-transform:uppercase;color:inherit;opacity:.5}
222 .listingblock:hover code[data-lang]::before{display:block}
223 .listingblock.terminal pre .command::before{content:attr(data-prompt);padding-right:.5em;color:inherit;opacity:.5}
224 .listingblock.terminal pre .command:not([data-prompt])::before{content:"$"}
225 .listingblock pre.highlightjs{padding:0}
226 .listingblock pre.highlightjs>code{padding:1em;border-radius:4px}
227 .listingblock pre.prettyprint{border-width:0}
228 .prettyprint{background:#f7f7f8}
229 pre.prettyprint .linenums{line-height:1.45;margin-left:2em}
230 pre.prettyprint li{background:none;list-style-type:inherit;padding-left:0}
231 pre.prettyprint li code[data-lang]::before{opacity:1}
232 pre.prettyprint li:not(:first-child) code[data-lang]::before{display:none}
233 table.linenotable{border-collapse:separate;border:0;margin-bottom:0;background:none}
234 table.linenotable td[class]{color:inherit;vertical-align:top;padding:0;line-height:inherit;white-space:normal}
235 table.linenotable td.code{padding-left:.75em}
236 table.linenotable td.linenos,pre.pygments .linenos{border-right:1px solid;opacity:.35;padding-right:.5em;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}
237 pre.pygments span.linenos{display:inline-block;margin-right:.75em}
238 .quoteblock{margin:0 1em 1.25em 1.5em;display:table}
239 .quoteblock:not(.excerpt)>.title{margin-left:-1.5em;margin-bottom:.75em}
240 .quoteblock blockquote,.quoteblock p{color:rgba(0,0,0,.85);font-size:1.15rem;line-height:1.75;word-spacing:.1em;letter-spacing:0;font-style:italic;text-align:justify}
241 .quoteblock blockquote{margin:0;padding:0;border:0}
242 .quoteblock blockquote::before{content:"\201c";float:left;font-size:2.75em;font-weight:bold;line-height:.6em;margin-left:-.6em;color:#7a2518;text-shadow:0 1px 2px rgba(0,0,0,.1)}
243 .quoteblock blockquote>.paragraph:last-child p{margin-bottom:0}
244 .quoteblock .attribution{margin-top:.75em;margin-right:.5ex;text-align:right}
245 .verseblock{margin:0 1em 1.25em}
246 .verseblock pre{font-family:"Open Sans","DejaVu Sans",sans-serif;font-size:1.15rem;color:rgba(0,0,0,.85);font-weight:300;text-rendering:optimizeLegibility}
247 .verseblock pre strong{font-weight:400}
248 .verseblock .attribution{margin-top:1.25rem;margin-left:.5ex}
249 .quoteblock .attribution,.verseblock .attribution{font-size:.9375em;line-height:1.45;font-style:italic}
250 .quoteblock .attribution br,.verseblock .attribution br{display:none}
251 .quoteblock .attribution cite,.verseblock .attribution cite{display:block;letter-spacing:-.025em;color:rgba(0,0,0,.6)}
252 .quoteblock.abstract blockquote::before,.quoteblock.excerpt blockquote::before,.quoteblock .quoteblock blockquote::before{display:none}
253 .quoteblock.abstract blockquote,.quoteblock.abstract p,.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{line-height:1.6;word-spacing:0}
254 .quoteblock.abstract{margin:0 1em 1.25em;display:block}
255 .quoteblock.abstract>.title{margin:0 0 .375em;font-size:1.15em;text-align:center}
256 .quoteblock.excerpt>blockquote,.quoteblock .quoteblock{padding:0 0 .25em 1em;border-left:.25em solid #dddddf}
257 .quoteblock.excerpt,.quoteblock .quoteblock{margin-left:0}
258 .quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{color:inherit;font-size:1.0625rem}
259 .quoteblock.excerpt .attribution,.quoteblock .quoteblock .attribution{color:inherit;font-size:.85rem;text-align:left;margin-right:0}
260 p.tableblock:last-child{margin-bottom:0}
261 td.tableblock>.content{margin-bottom:1.25em;word-wrap:anywhere}
262 td.tableblock>.content>:last-child{margin-bottom:-1.25em}
263 table.tableblock,th.tableblock,td.tableblock{border:0 solid #dedede}
264 table.grid-all>*>tr>*{border-width:1px}
265 table.grid-cols>*>tr>*{border-width:0 1px}
266 table.grid-rows>*>tr>*{border-width:1px 0}
267 table.frame-all{border-width:1px}
268 table.frame-ends{border-width:1px 0}
269 table.frame-sides{border-width:0 1px}
270 table.frame-none>colgroup+*>:first-child>*,table.frame-sides>colgroup+*>:first-child>*{border-top-width:0}
271 table.frame-none>:last-child>:last-child>*,table.frame-sides>:last-child>:last-child>*{border-bottom-width:0}
272 table.frame-none>*>tr>:first-child,table.frame-ends>*>tr>:first-child{border-left-width:0}
273 table.frame-none>*>tr>:last-child,table.frame-ends>*>tr>:last-child{border-right-width:0}
274 table.stripes-all>*>tr,table.stripes-odd>*>tr:nth-of-type(odd),table.stripes-even>*>tr:nth-of-type(even),table.stripes-hover>*>tr:hover{background:#f8f8f7}
275 th.halign-left,td.halign-left{text-align:left}
276 th.halign-right,td.halign-right{text-align:right}
277 th.halign-center,td.halign-center{text-align:center}
278 th.valign-top,td.valign-top{vertical-align:top}
279 th.valign-bottom,td.valign-bottom{vertical-align:bottom}
280 th.valign-middle,td.valign-middle{vertical-align:middle}
281 table thead th,table tfoot th{font-weight:bold}
282 tbody tr th{background:#f7f8f7}
283 tbody tr th,tbody tr th p,tfoot tr th,tfoot tr th p{color:rgba(0,0,0,.8);font-weight:bold}
284 p.tableblock>code:only-child{background:none;padding:0}
285 p.tableblock{font-size:1em}
286 ol{margin-left:1.75em}
287 ul li ol{margin-left:1.5em}
288 dl dd{margin-left:1.125em}
289 dl dd:last-child,dl dd:last-child>:last-child{margin-bottom:0}
290 li p,ul dd,ol dd,.olist .olist,.ulist .ulist,.ulist .olist,.olist .ulist{margin-bottom:.625em}
291 ul.checklist,ul.none,ol.none,ul.no-bullet,ol.no-bullet,ol.unnumbered,ul.unstyled,ol.unstyled{list-style-type:none}
292 ul.no-bullet,ol.no-bullet,ol.unnumbered{margin-left:.625em}
293 ul.unstyled,ol.unstyled{margin-left:0}
294 li>p:empty:only-child::before{content:"";display:inline-block}
295 ul.checklist>li>p:first-child{margin-left:-1em}
296 ul.checklist>li>p:first-child>.fa-square-o:first-child,ul.checklist>li>p:first-child>.fa-check-square-o:first-child{width:1.25em;font-size:.8em;position:relative;bottom:.125em}
297 ul.checklist>li>p:first-child>input[type=checkbox]:first-child{margin-right:.25em}
298 ul.inline{display:flex;flex-flow:row wrap;list-style:none;margin:0 0 .625em -1.25em}
299 ul.inline>li{margin-left:1.25em}
300 .unstyled dl dt{font-weight:400;font-style:normal}
301 ol.arabic{list-style-type:decimal}
302 ol.decimal{list-style-type:decimal-leading-zero}
303 ol.loweralpha{list-style-type:lower-alpha}
304 ol.upperalpha{list-style-type:upper-alpha}
305 ol.lowerroman{list-style-type:lower-roman}
306 ol.upperroman{list-style-type:upper-roman}
307 ol.lowergreek{list-style-type:lower-greek}
308 .hdlist>table,.colist>table{border:0;background:none}
309 .hdlist>table>tbody>tr,.colist>table>tbody>tr{background:none}
310 td.hdlist1,td.hdlist2{vertical-align:top;padding:0 .625em}
311 td.hdlist1{font-weight:bold;padding-bottom:1.25em}
312 td.hdlist2{word-wrap:anywhere}
313 .literalblock+.colist,.listingblock+.colist{margin-top:-.5em}
314 .colist td:not([class]):first-child{padding:.4em .75em 0;line-height:1;vertical-align:top}
315 .colist td:not([class]):first-child img{max-width:none}
316 .colist td:not([class]):last-child{padding:.25em 0}
317 .thumb,.th{line-height:0;display:inline-block;border:4px solid #fff;box-shadow:0 0 0 1px #ddd}
318 .imageblock.left{margin:.25em .625em 1.25em 0}
319 .imageblock.right{margin:.25em 0 1.25em .625em}
320 .imageblock>.title{margin-bottom:0}
321 .imageblock.thumb,.imageblock.th{border-width:6px}
322 .imageblock.thumb>.title,.imageblock.th>.title{padding:0 .125em}
323 .image.left,.image.right{margin-top:.25em;margin-bottom:.25em;display:inline-block;line-height:0}
324 .image.left{margin-right:.625em}
325 .image.right{margin-left:.625em}
326 a.image{text-decoration:none;display:inline-block}
327 a.image object{pointer-events:none}
328 sup.footnote,sup.footnoteref{font-size:.875em;position:static;vertical-align:super}
329 sup.footnote a,sup.footnoteref a{text-decoration:none}
330 sup.footnote a:active,sup.footnoteref a:active{text-decoration:underline}
331 #footnotes{padding-top:.75em;padding-bottom:.75em;margin-bottom:.625em}
332 #footnotes hr{width:20%;min-width:6.25em;margin:-.25em 0 .75em;border-width:1px 0 0}
333 #footnotes .footnote{padding:0 .375em 0 .225em;line-height:1.3334;font-size:.875em;margin-left:1.2em;margin-bottom:.2em}
334 #footnotes .footnote a:first-of-type{font-weight:bold;text-decoration:none;margin-left:-1.05em}
335 #footnotes .footnote:last-of-type{margin-bottom:0}
336 #content #footnotes{margin-top:-.625em;margin-bottom:0;padding:.75em 0}
337 div.unbreakable{page-break-inside:avoid}
338 .big{font-size:larger}
339 .small{font-size:smaller}
340 .underline{text-decoration:underline}
341 .overline{text-decoration:overline}
342 .line-through{text-decoration:line-through}
343 .aqua{color:#00bfbf}
344 .aqua-background{background:#00fafa}
345 .black{color:#000}
346 .black-background{background:#000}
347 .blue{color:#0000bf}
348 .blue-background{background:#0000fa}
349 .fuchsia{color:#bf00bf}
350 .fuchsia-background{background:#fa00fa}
351 .gray{color:#606060}
352 .gray-background{background:#7d7d7d}
353 .green{color:#006000}
354 .green-background{background:#007d00}
355 .lime{color:#00bf00}
356 .lime-background{background:#00fa00}
357 .maroon{color:#600000}
358 .maroon-background{background:#7d0000}
359 .navy{color:#000060}
360 .navy-background{background:#00007d}
361 .olive{color:#606000}
362 .olive-background{background:#7d7d00}
363 .purple{color:#600060}
364 .purple-background{background:#7d007d}
365 .red{color:#bf0000}
366 .red-background{background:#fa0000}
367 .silver{color:#909090}
368 .silver-background{background:#bcbcbc}
369 .teal{color:#006060}
370 .teal-background{background:#007d7d}
371 .white{color:#bfbfbf}
372 .white-background{background:#fafafa}
373 .yellow{color:#bfbf00}
374 .yellow-background{background:#fafa00}
375 span.icon>.fa{cursor:default}
376 a span.icon>.fa{cursor:inherit}
377 .admonitionblock td.icon [class^="fa icon-"]{font-size:2.5em;text-shadow:1px 1px 2px rgba(0,0,0,.5);cursor:default}
378 .admonitionblock td.icon .icon-note::before{content:"\f05a";color:#19407c}
379 .admonitionblock td.icon .icon-tip::before{content:"\f0eb";text-shadow:1px 1px 2px rgba(155,155,0,.8);color:#111}
380 .admonitionblock td.icon .icon-warning::before{content:"\f071";color:#bf6900}
381 .admonitionblock td.icon .icon-caution::before{content:"\f06d";color:#bf3400}
382 .admonitionblock td.icon .icon-important::before{content:"\f06a";color:#bf0000}
383 .conum[data-value]{display:inline-block;color:#fff!important;background:rgba(0,0,0,.8);border-radius:50%;text-align:center;font-size:.75em;width:1.67em;height:1.67em;line-height:1.67em;font-family:"Open Sans","DejaVu Sans",sans-serif;font-style:normal;font-weight:bold}
384 .conum[data-value] *{color:#fff!important}
385 .conum[data-value]+b{display:none}
386 .conum[data-value]::after{content:attr(data-value)}
387 pre .conum[data-value]{position:relative;top:-.125em}
388 b.conum *{color:inherit!important}
389 .conum:not([data-value]):empty{display:none}
390 dt,th.tableblock,td.content,div.footnote{text-rendering:optimizeLegibility}
391 h1,h2,p,td.content,span.alt,summary{letter-spacing:-.01em}
392 p strong,td.content strong,div.footnote strong{letter-spacing:-.005em}
393 p,blockquote,dt,td.content,td.hdlist1,span.alt,summary{font-size:1.0625rem}
394 p{margin-bottom:1.25rem}
395 .sidebarblock p,.sidebarblock dt,.sidebarblock td.content,p.tableblock{font-size:1em}
396 .exampleblock>.content{background:#fffef7;border-color:#e0e0dc;box-shadow:0 1px 4px #e0e0dc}
397 .print-only{display:none!important}
398 @page{margin:1.25cm .75cm}
399 @media print{*{box-shadow:none!important;text-shadow:none!important}
400 html{font-size:80%}
401 a{color:inherit!important;text-decoration:underline!important}
402 a.bare,a[href^="#"],a[href^="mailto:"]{text-decoration:none!important}
403 a[href^="http:"]:not(.bare)::after,a[href^="https:"]:not(.bare)::after{content:"(" attr(href) ")";display:inline-block;font-size:.875em;padding-left:.25em}
404 abbr[title]{border-bottom:1px dotted}
405 abbr[title]::after{content:" (" attr(title) ")"}
406 pre,blockquote,tr,img,object,svg{page-break-inside:avoid}
407 thead{display:table-header-group}
408 svg{max-width:100%}
409 p,blockquote,dt,td.content{font-size:1em;orphans:3;widows:3}
410 h2,h3,#toctitle,.sidebarblock>.content>.title{page-break-after:avoid}
411 #header,#content,#footnotes,#footer{max-width:none}
412 #toc,.sidebarblock,.exampleblock>.content{background:none!important}
413 #toc{border-bottom:1px solid #dddddf!important;padding-bottom:0!important}
414 body.book #header{text-align:center}
415 body.book #header>h1:first-child{border:0!important;margin:2.5em 0 1em}
416 body.book #header .details{border:0!important;display:block;padding:0!important}
417 body.book #header .details span:first-child{margin-left:0!important}
418 body.book #header .details br{display:block}
419 body.book #header .details br+span::before{content:none!important}
420 body.book #toc{border:0!important;text-align:left!important;padding:0!important;margin:0!important}
421 body.book #toc,body.book #preamble,body.book h1.sect0,body.book .sect1>h2{page-break-before:always}
422 .listingblock code[data-lang]::before{display:block}
423 #footer{padding:0 .9375em}
424 .hide-on-print{display:none!important}
425 .print-only{display:block!important}
426 .hide-for-print{display:none!important}
427 .show-for-print{display:inherit!important}}
428 @media amzn-kf8,print{#header>h1:first-child{margin-top:1.25rem}
429 .sect1{padding:0!important}
430 .sect1+.sect1{border:0}
431 #footer{background:none}
432 #footer-text{color:rgba(0,0,0,.6);font-size:.9em}}
433 @media amzn-kf8{#header,#content,#footnotes,#footer{padding:0}}
434 </style>
435 <style>
436 pre>code {
437 display: inline;
439 </style>
440 </head>
441 <body class="article">
442 <div id="header">
443 <h1>How to recover an object from scratch</h1>
444 </div>
445 <div id="content">
446 <div id="preamble">
447 <div class="sectionbody">
448 <div class="paragraph">
449 <p>I was recently presented with a repository with a corrupted packfile,
450 and was asked if the data was recoverable. This post-mortem describes
451 the steps I took to investigate and fix the problem. I thought others
452 might find the process interesting, and it might help somebody in the
453 same situation.</p>
454 </div>
455 <div class="sidebarblock">
456 <div class="content">
457 <div class="paragraph">
458 <p>Note: In this case, no good copy of the repository was available. For
459 the much easier case where you can get the corrupted object from
460 elsewhere, see <a href="recover-corrupted-blob-object.html">this howto</a>.</p>
461 </div>
462 </div>
463 </div>
464 <div class="paragraph">
465 <p>I started with an fsck, which found a problem with exactly one object
466 (I&#8217;ve used $pack and $obj below to keep the output readable, and also
467 because I&#8217;ll refer to them later):</p>
468 </div>
469 <div class="listingblock">
470 <div class="content">
471 <pre> $ git fsck
472 error: $pack SHA1 checksum mismatch
473 error: index CRC mismatch for object $obj from $pack at offset 51653873
474 error: inflate: data stream error (incorrect data check)
475 error: cannot unpack $obj from $pack at offset 51653873</pre>
476 </div>
477 </div>
478 <div class="paragraph">
479 <p>The pack checksum failing means a byte is munged somewhere, and it is
480 presumably in the object mentioned (since both the index checksum and
481 zlib were failing).</p>
482 </div>
483 <div class="paragraph">
484 <p>Reading the zlib source code, I found that "incorrect data check" means
485 that the adler-32 checksum at the end of the zlib data did not match the
486 inflated data. So stepping the data through zlib would not help, as it
487 did not fail until the very end, when we realize the CRC does not match.
488 The problematic bytes could be anywhere in the object data.</p>
489 </div>
490 <div class="paragraph">
491 <p>The first thing I did was pull the broken data out of the packfile. I
492 needed to know how big the object was, which I found out with:</p>
493 </div>
494 <div class="listingblock">
495 <div class="content">
496 <pre> $ git show-index &lt;$idx | cut -d' ' -f1 | sort -n | grep -A1 51653873
497 51653873
498 51664736</pre>
499 </div>
500 </div>
501 <div class="paragraph">
502 <p>Show-index gives us the list of objects and their offsets. We throw away
503 everything but the offsets, and then sort them so that our interesting
504 offset (which we got from the fsck output above) is followed immediately
505 by the offset of the next object. Now we know that the object data is
506 10863 bytes long, and we can grab it with:</p>
507 </div>
508 <div class="listingblock">
509 <div class="content">
510 <pre> dd if=$pack of=object bs=1 skip=51653873 count=10863</pre>
511 </div>
512 </div>
513 <div class="paragraph">
514 <p>I inspected a hexdump of the data, looking for any obvious bogosity
515 (e.g., a 4K run of zeroes would be a good sign of filesystem
516 corruption). But everything looked pretty reasonable.</p>
517 </div>
518 <div class="paragraph">
519 <p>Note that the "object" file isn&#8217;t fit for feeding straight to zlib; it
520 has the git packed object header, which is variable-length. We want to
521 strip that off so we can start playing with the zlib data directly. You
522 can either work your way through it manually (the format is described in
523 <a href="../gitformat-pack.html">gitformat-pack(5)</a>),
524 or you can walk through it in a debugger. I did the latter, creating a
525 valid pack like:</p>
526 </div>
527 <div class="listingblock">
528 <div class="content">
529 <pre> # pack magic and version
530 printf 'PACK\0\0\0\2' &gt;tmp.pack
531 # pack has one object
532 printf '\0\0\0\1' &gt;&gt;tmp.pack
533 # now add our object data
534 cat object &gt;&gt;tmp.pack
535 # and then append the pack trailer
536 /path/to/git.git/t/helper/test-tool sha1 -b &lt;tmp.pack &gt;trailer
537 cat trailer &gt;&gt;tmp.pack</pre>
538 </div>
539 </div>
540 <div class="paragraph">
541 <p>and then running "git index-pack tmp.pack" in the debugger (stop at
542 unpack_raw_entry). Doing this, I found that there were 3 bytes of header
543 (and the header itself had a sane type and size). So I stripped those
544 off with:</p>
545 </div>
546 <div class="listingblock">
547 <div class="content">
548 <pre> dd if=object of=zlib bs=1 skip=3</pre>
549 </div>
550 </div>
551 <div class="paragraph">
552 <p>I ran the result through zlib&#8217;s inflate using a custom C program. And
553 while it did report the error, I did get the right number of output
554 bytes (i.e., it matched git&#8217;s size header that we decoded above). But
555 feeding the result back to "git hash-object" didn&#8217;t produce the same
556 sha1. So there were some wrong bytes, but I didn&#8217;t know which. The file
557 happened to be C source code, so I hoped I could notice something
558 obviously wrong with it, but I didn&#8217;t. I even got it to compile!</p>
559 </div>
560 <div class="paragraph">
561 <p>I also tried comparing it to other versions of the same path in the
562 repository, hoping that there would be some part of the diff that didn&#8217;t
563 make sense. Unfortunately, this happened to be the only revision of this
564 particular file in the repository, so I had nothing to compare against.</p>
565 </div>
566 <div class="paragraph">
567 <p>So I took a different approach. Working under the guess that the
568 corruption was limited to a single byte, I wrote a program to munge each
569 byte individually, and try inflating the result. Since the object was
570 only 10K compressed, that worked out to about 2.5M attempts, which took
571 a few minutes.</p>
572 </div>
573 <div class="paragraph">
574 <p>The program I used is here:</p>
575 </div>
576 <div class="listingblock">
577 <div class="content">
578 <pre>#include &lt;stdio.h&gt;
579 #include &lt;unistd.h&gt;
580 #include &lt;string.h&gt;
581 #include &lt;signal.h&gt;
582 #include &lt;zlib.h&gt;
584 static int try_zlib(unsigned char *buf, int len)
586 /* make this absurdly large so we don't have to loop */
587 static unsigned char out[1024*1024];
588 z_stream z;
589 int ret;
591 memset(&amp;z, 0, sizeof(z));
592 inflateInit(&amp;z);
594 z.next_in = buf;
595 z.avail_in = len;
596 z.next_out = out;
597 z.avail_out = sizeof(out);
599 ret = inflate(&amp;z, 0);
600 inflateEnd(&amp;z);
601 return ret &gt;= 0;
604 /* eye candy */
605 static int counter = 0;
606 static void progress(int sig)
608 fprintf(stderr, "\r%d", counter);
609 alarm(1);
612 int main(void)
614 /* oversized so we can read the whole buffer in */
615 unsigned char buf[1024*1024];
616 int len;
617 unsigned i, j;
619 signal(SIGALRM, progress);
620 alarm(1);
622 len = read(0, buf, sizeof(buf));
623 for (i = 0; i &lt; len; i++) {
624 unsigned char c = buf[i];
625 for (j = 0; j &lt;= 0xff; j++) {
626 buf[i] = j;
628 counter++;
629 if (try_zlib(buf, len))
630 printf("i=%d, j=%x\n", i, j);
632 buf[i] = c;
635 alarm(0);
636 fprintf(stderr, "\n");
637 return 0;
638 }</pre>
639 </div>
640 </div>
641 <div class="paragraph">
642 <p>I compiled and ran with:</p>
643 </div>
644 <div class="listingblock">
645 <div class="content">
646 <pre> gcc -Wall -Werror -O3 munge.c -o munge -lz
647 ./munge &lt;zlib</pre>
648 </div>
649 </div>
650 <div class="paragraph">
651 <p>There were a few false positives early on (if you write "no data" in the
652 zlib header, zlib thinks it&#8217;s just fine :) ). But I got a hit about
653 halfway through:</p>
654 </div>
655 <div class="listingblock">
656 <div class="content">
657 <pre> i=5642, j=c7</pre>
658 </div>
659 </div>
660 <div class="paragraph">
661 <p>I let it run to completion, and got a few more hits at the end (where it
662 was munging the CRC to match our broken data). So there was a good
663 chance this middle hit was the source of the problem.</p>
664 </div>
665 <div class="paragraph">
666 <p>I confirmed by tweaking the byte in a hex editor, zlib inflating the
667 result (no errors!), and then piping the output into "git hash-object",
668 which reported the sha1 of the broken object. Success!</p>
669 </div>
670 <div class="paragraph">
671 <p>I fixed the packfile itself with:</p>
672 </div>
673 <div class="listingblock">
674 <div class="content">
675 <pre> chmod +w $pack
676 printf '\xc7' | dd of=$pack bs=1 seek=51659518 conv=notrunc
677 chmod -w $pack</pre>
678 </div>
679 </div>
680 <div class="paragraph">
681 <p>The \xc7 comes from the replacement byte our "munge" program found.
682 The offset 51659518 is derived by taking the original object offset
683 (51653873), adding the replacement offset found by "munge" (5642), and
684 then adding back in the 3 bytes of git header we stripped.</p>
685 </div>
686 <div class="paragraph">
687 <p>After that, "git fsck" ran clean.</p>
688 </div>
689 <div class="paragraph">
690 <p>As for the corruption itself, I was lucky that it was indeed a single
691 byte. In fact, it turned out to be a single bit. The byte 0xc7 was
692 corrupted to 0xc5. So presumably it was caused by faulty hardware, or a
693 cosmic ray.</p>
694 </div>
695 <div class="paragraph">
696 <p>And the aborted attempt to look at the inflated output to see what was
697 wrong? I could have looked forever and never found it. Here&#8217;s the diff
698 between what the corrupted data inflates to, versus the real data:</p>
699 </div>
700 <div class="listingblock">
701 <div class="content">
702 <pre> - cp = strtok (arg, "+");
703 + cp = strtok (arg, ".");</pre>
704 </div>
705 </div>
706 <div class="paragraph">
707 <p>It tweaked one byte and still ended up as valid, readable C that just
708 happened to do something totally different! One takeaway is that on a
709 less unlucky day, looking at the zlib output might have actually been
710 helpful, as most random changes would actually break the C code.</p>
711 </div>
712 <div class="paragraph">
713 <p>But more importantly, git&#8217;s hashing and checksumming noticed a problem
714 that easily could have gone undetected in another system. The result
715 still compiled, but would have caused an interesting bug (that would
716 have been blamed on some random commit).</p>
717 </div>
718 </div>
719 </div>
720 <div class="sect1">
721 <h2 id="_the_adventure_continues">The adventure continues&#8230;&#8203;</h2>
722 <div class="sectionbody">
723 <div class="paragraph">
724 <p>I ended up doing this again! Same entity, new hardware. The assumption
725 at this point is that the old disk corrupted the packfile, and then the
726 corruption was migrated to the new hardware (because it was done by
727 rsync or similar, and no fsck was done at the time of migration).</p>
728 </div>
729 <div class="paragraph">
730 <p>This time, the affected blob was over 20 megabytes, which was far too
731 large to do a brute-force on. I followed the instructions above to
732 create the <code>zlib</code> file. I then used the <code>inflate</code> program below to pull
733 the corrupted data from that. Examining that output gave me a hint about
734 where in the file the corruption was. But now I was working with the
735 file itself, not the zlib contents. So knowing the sha1 of the object
736 and the approximate area of the corruption, I used the <code>sha1-munge</code>
737 program below to brute-force the correct byte.</p>
738 </div>
739 <div class="paragraph">
740 <p>Here&#8217;s the inflate program (it&#8217;s essentially <code>gunzip</code> but without the
741 .<code>gz</code> header processing):</p>
742 </div>
743 <div class="listingblock">
744 <div class="content">
745 <pre>#include &lt;stdio.h&gt;
746 #include &lt;string.h&gt;
747 #include &lt;zlib.h&gt;
748 #include &lt;stdlib.h&gt;
750 int main(int argc, char **argv)
753 * oversized so we can read the whole buffer in;
754 * this could actually be switched to streaming
755 * to avoid any memory limitations
757 static unsigned char buf[25 * 1024 * 1024];
758 static unsigned char out[25 * 1024 * 1024];
759 int len;
760 z_stream z;
761 int ret;
763 len = read(0, buf, sizeof(buf));
764 memset(&amp;z, 0, sizeof(z));
765 inflateInit(&amp;z);
767 z.next_in = buf;
768 z.avail_in = len;
769 z.next_out = out;
770 z.avail_out = sizeof(out);
772 ret = inflate(&amp;z, 0);
773 if (ret != Z_OK &amp;&amp; ret != Z_STREAM_END)
774 fprintf(stderr, "initial inflate failed (%d)\n", ret);
776 fprintf(stderr, "outputting %lu bytes", z.total_out);
777 fwrite(out, 1, z.total_out, stdout);
778 return 0;
779 }</pre>
780 </div>
781 </div>
782 <div class="paragraph">
783 <p>And here is the <code>sha1-munge</code> program:</p>
784 </div>
785 <div class="listingblock">
786 <div class="content">
787 <pre>#include &lt;stdio.h&gt;
788 #include &lt;unistd.h&gt;
789 #include &lt;string.h&gt;
790 #include &lt;signal.h&gt;
791 #include &lt;openssl/sha.h&gt;
792 #include &lt;stdlib.h&gt;
794 /* eye candy */
795 static int counter = 0;
796 static void progress(int sig)
798 fprintf(stderr, "\r%d", counter);
799 alarm(1);
802 static const signed char hexval_table[256] = {
803 -1, -1, -1, -1, -1, -1, -1, -1, /* 00-07 */
804 -1, -1, -1, -1, -1, -1, -1, -1, /* 08-0f */
805 -1, -1, -1, -1, -1, -1, -1, -1, /* 10-17 */
806 -1, -1, -1, -1, -1, -1, -1, -1, /* 18-1f */
807 -1, -1, -1, -1, -1, -1, -1, -1, /* 20-27 */
808 -1, -1, -1, -1, -1, -1, -1, -1, /* 28-2f */
809 0, 1, 2, 3, 4, 5, 6, 7, /* 30-37 */
810 8, 9, -1, -1, -1, -1, -1, -1, /* 38-3f */
811 -1, 10, 11, 12, 13, 14, 15, -1, /* 40-47 */
812 -1, -1, -1, -1, -1, -1, -1, -1, /* 48-4f */
813 -1, -1, -1, -1, -1, -1, -1, -1, /* 50-57 */
814 -1, -1, -1, -1, -1, -1, -1, -1, /* 58-5f */
815 -1, 10, 11, 12, 13, 14, 15, -1, /* 60-67 */
816 -1, -1, -1, -1, -1, -1, -1, -1, /* 68-67 */
817 -1, -1, -1, -1, -1, -1, -1, -1, /* 70-77 */
818 -1, -1, -1, -1, -1, -1, -1, -1, /* 78-7f */
819 -1, -1, -1, -1, -1, -1, -1, -1, /* 80-87 */
820 -1, -1, -1, -1, -1, -1, -1, -1, /* 88-8f */
821 -1, -1, -1, -1, -1, -1, -1, -1, /* 90-97 */
822 -1, -1, -1, -1, -1, -1, -1, -1, /* 98-9f */
823 -1, -1, -1, -1, -1, -1, -1, -1, /* a0-a7 */
824 -1, -1, -1, -1, -1, -1, -1, -1, /* a8-af */
825 -1, -1, -1, -1, -1, -1, -1, -1, /* b0-b7 */
826 -1, -1, -1, -1, -1, -1, -1, -1, /* b8-bf */
827 -1, -1, -1, -1, -1, -1, -1, -1, /* c0-c7 */
828 -1, -1, -1, -1, -1, -1, -1, -1, /* c8-cf */
829 -1, -1, -1, -1, -1, -1, -1, -1, /* d0-d7 */
830 -1, -1, -1, -1, -1, -1, -1, -1, /* d8-df */
831 -1, -1, -1, -1, -1, -1, -1, -1, /* e0-e7 */
832 -1, -1, -1, -1, -1, -1, -1, -1, /* e8-ef */
833 -1, -1, -1, -1, -1, -1, -1, -1, /* f0-f7 */
834 -1, -1, -1, -1, -1, -1, -1, -1, /* f8-ff */
837 static inline unsigned int hexval(unsigned char c)
839 return hexval_table[c];
842 static int get_sha1_hex(const char *hex, unsigned char *sha1)
844 int i;
845 for (i = 0; i &lt; 20; i++) {
846 unsigned int val;
848 * hex[1]=='\0' is caught when val is checked below,
849 * but if hex[0] is NUL we have to avoid reading
850 * past the end of the string:
852 if (!hex[0])
853 return -1;
854 val = (hexval(hex[0]) &lt;&lt; 4) | hexval(hex[1]);
855 if (val &amp; ~0xff)
856 return -1;
857 *sha1++ = val;
858 hex += 2;
860 return 0;
863 int main(int argc, char **argv)
865 /* oversized so we can read the whole buffer in */
866 static unsigned char buf[25 * 1024 * 1024];
867 char header[32];
868 int header_len;
869 unsigned char have[20], want[20];
870 int start, len;
871 SHA_CTX orig;
872 unsigned i, j;
874 if (!argv[1] || get_sha1_hex(argv[1], want)) {
875 fprintf(stderr, "usage: sha1-munge &lt;sha1&gt; [start] &lt;file.in\n");
876 return 1;
879 if (argv[2])
880 start = atoi(argv[2]);
881 else
882 start = 0;
884 len = read(0, buf, sizeof(buf));
885 header_len = sprintf(header, "blob %d", len) + 1;
886 fprintf(stderr, "using header: %s\n", header);
889 * We keep a running sha1 so that if you are munging
890 * near the end of the file, we do not have to re-sha1
891 * the unchanged earlier bytes
893 SHA1_Init(&amp;orig);
894 SHA1_Update(&amp;orig, header, header_len);
895 if (start)
896 SHA1_Update(&amp;orig, buf, start);
898 signal(SIGALRM, progress);
899 alarm(1);
901 for (i = start; i &lt; len; i++) {
902 unsigned char c;
903 SHA_CTX x;
905 #if 0
907 * deletion -- this would not actually work in practice,
908 * I think, because we've already committed to a
909 * particular size in the header. Ditto for addition
910 * below. In those cases, you'd have to do the whole
911 * sha1 from scratch, or possibly keep three running
912 * "orig" sha1 computations going.
914 memcpy(&amp;x, &amp;orig, sizeof(x));
915 SHA1_Update(&amp;x, buf + i + 1, len - i - 1);
916 SHA1_Final(have, &amp;x);
917 if (!memcmp(have, want, 20))
918 printf("i=%d, deletion\n", i);
919 #endif
922 * replacement -- note that this tries each of the 256
923 * possible bytes. If you suspect a single-bit flip,
924 * it would be much shorter to just try the 8
925 * bit-flipped variants.
927 c = buf[i];
928 for (j = 0; j &lt;= 0xff; j++) {
929 buf[i] = j;
931 memcpy(&amp;x, &amp;orig, sizeof(x));
932 SHA1_Update(&amp;x, buf + i, len - i);
933 SHA1_Final(have, &amp;x);
934 if (!memcmp(have, want, 20))
935 printf("i=%d, j=%02x\n", i, j);
937 buf[i] = c;
939 #if 0
940 /* addition */
941 for (j = 0; j &lt;= 0xff; j++) {
942 unsigned char extra = j;
943 memcpy(&amp;x, &amp;orig, sizeof(x));
944 SHA1_Update(&amp;x, &amp;extra, 1);
945 SHA1_Update(&amp;x, buf + i, len - i);
946 SHA1_Final(have, &amp;x);
947 if (!memcmp(have, want, 20))
948 printf("i=%d, addition=%02x", i, j);
950 #endif
952 SHA1_Update(&amp;orig, buf + i, 1);
953 counter++;
956 alarm(0);
957 fprintf(stderr, "\r%d\n", counter);
958 return 0;
959 }</pre>
960 </div>
961 </div>
962 </div>
963 </div>
964 </div>
965 <div id="footer">
966 <div id="footer-text">
967 Last updated 2025-01-10 09:40:20 -0800
968 </div>
969 </div>
970 </body>
971 </html>