Autogenerated HTML docs for v2.46.0-348-g6a09c36
[git-htmldocs.git] / howto / recover-corrupted-object-harder.html
blob75c67c39facb65dd9f7800dd81cec068e4d710cc
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 class="details">
445 <span id="revdate">2024-08-23</span>
446 </div>
447 </div>
448 <div id="content">
449 <div id="preamble">
450 <div class="sectionbody">
451 <div class="paragraph">
452 <p>I was recently presented with a repository with a corrupted packfile,
453 and was asked if the data was recoverable. This post-mortem describes
454 the steps I took to investigate and fix the problem. I thought others
455 might find the process interesting, and it might help somebody in the
456 same situation.</p>
457 </div>
458 <div class="sidebarblock">
459 <div class="content">
460 <div class="paragraph">
461 <p>Note: In this case, no good copy of the repository was available. For
462 the much easier case where you can get the corrupted object from
463 elsewhere, see <a href="recover-corrupted-blob-object.html">this howto</a>.</p>
464 </div>
465 </div>
466 </div>
467 <div class="paragraph">
468 <p>I started with an fsck, which found a problem with exactly one object
469 (I&#8217;ve used $pack and $obj below to keep the output readable, and also
470 because I&#8217;ll refer to them later):</p>
471 </div>
472 <div class="listingblock">
473 <div class="content">
474 <pre> $ git fsck
475 error: $pack SHA1 checksum mismatch
476 error: index CRC mismatch for object $obj from $pack at offset 51653873
477 error: inflate: data stream error (incorrect data check)
478 error: cannot unpack $obj from $pack at offset 51653873</pre>
479 </div>
480 </div>
481 <div class="paragraph">
482 <p>The pack checksum failing means a byte is munged somewhere, and it is
483 presumably in the object mentioned (since both the index checksum and
484 zlib were failing).</p>
485 </div>
486 <div class="paragraph">
487 <p>Reading the zlib source code, I found that "incorrect data check" means
488 that the adler-32 checksum at the end of the zlib data did not match the
489 inflated data. So stepping the data through zlib would not help, as it
490 did not fail until the very end, when we realize the CRC does not match.
491 The problematic bytes could be anywhere in the object data.</p>
492 </div>
493 <div class="paragraph">
494 <p>The first thing I did was pull the broken data out of the packfile. I
495 needed to know how big the object was, which I found out with:</p>
496 </div>
497 <div class="listingblock">
498 <div class="content">
499 <pre> $ git show-index &lt;$idx | cut -d' ' -f1 | sort -n | grep -A1 51653873
500 51653873
501 51664736</pre>
502 </div>
503 </div>
504 <div class="paragraph">
505 <p>Show-index gives us the list of objects and their offsets. We throw away
506 everything but the offsets, and then sort them so that our interesting
507 offset (which we got from the fsck output above) is followed immediately
508 by the offset of the next object. Now we know that the object data is
509 10863 bytes long, and we can grab it with:</p>
510 </div>
511 <div class="listingblock">
512 <div class="content">
513 <pre> dd if=$pack of=object bs=1 skip=51653873 count=10863</pre>
514 </div>
515 </div>
516 <div class="paragraph">
517 <p>I inspected a hexdump of the data, looking for any obvious bogosity
518 (e.g., a 4K run of zeroes would be a good sign of filesystem
519 corruption). But everything looked pretty reasonable.</p>
520 </div>
521 <div class="paragraph">
522 <p>Note that the "object" file isn&#8217;t fit for feeding straight to zlib; it
523 has the git packed object header, which is variable-length. We want to
524 strip that off so we can start playing with the zlib data directly. You
525 can either work your way through it manually (the format is described in
526 <a href="../gitformat-pack.html">gitformat-pack(5)</a>),
527 or you can walk through it in a debugger. I did the latter, creating a
528 valid pack like:</p>
529 </div>
530 <div class="listingblock">
531 <div class="content">
532 <pre> # pack magic and version
533 printf 'PACK\0\0\0\2' &gt;tmp.pack
534 # pack has one object
535 printf '\0\0\0\1' &gt;&gt;tmp.pack
536 # now add our object data
537 cat object &gt;&gt;tmp.pack
538 # and then append the pack trailer
539 /path/to/git.git/t/helper/test-tool sha1 -b &lt;tmp.pack &gt;trailer
540 cat trailer &gt;&gt;tmp.pack</pre>
541 </div>
542 </div>
543 <div class="paragraph">
544 <p>and then running "git index-pack tmp.pack" in the debugger (stop at
545 unpack_raw_entry). Doing this, I found that there were 3 bytes of header
546 (and the header itself had a sane type and size). So I stripped those
547 off with:</p>
548 </div>
549 <div class="listingblock">
550 <div class="content">
551 <pre> dd if=object of=zlib bs=1 skip=3</pre>
552 </div>
553 </div>
554 <div class="paragraph">
555 <p>I ran the result through zlib&#8217;s inflate using a custom C program. And
556 while it did report the error, I did get the right number of output
557 bytes (i.e., it matched git&#8217;s size header that we decoded above). But
558 feeding the result back to "git hash-object" didn&#8217;t produce the same
559 sha1. So there were some wrong bytes, but I didn&#8217;t know which. The file
560 happened to be C source code, so I hoped I could notice something
561 obviously wrong with it, but I didn&#8217;t. I even got it to compile!</p>
562 </div>
563 <div class="paragraph">
564 <p>I also tried comparing it to other versions of the same path in the
565 repository, hoping that there would be some part of the diff that didn&#8217;t
566 make sense. Unfortunately, this happened to be the only revision of this
567 particular file in the repository, so I had nothing to compare against.</p>
568 </div>
569 <div class="paragraph">
570 <p>So I took a different approach. Working under the guess that the
571 corruption was limited to a single byte, I wrote a program to munge each
572 byte individually, and try inflating the result. Since the object was
573 only 10K compressed, that worked out to about 2.5M attempts, which took
574 a few minutes.</p>
575 </div>
576 <div class="paragraph">
577 <p>The program I used is here:</p>
578 </div>
579 <div class="listingblock">
580 <div class="content">
581 <pre>#include &lt;stdio.h&gt;
582 #include &lt;unistd.h&gt;
583 #include &lt;string.h&gt;
584 #include &lt;signal.h&gt;
585 #include &lt;zlib.h&gt;
587 static int try_zlib(unsigned char *buf, int len)
589 /* make this absurdly large so we don't have to loop */
590 static unsigned char out[1024*1024];
591 z_stream z;
592 int ret;
594 memset(&amp;z, 0, sizeof(z));
595 inflateInit(&amp;z);
597 z.next_in = buf;
598 z.avail_in = len;
599 z.next_out = out;
600 z.avail_out = sizeof(out);
602 ret = inflate(&amp;z, 0);
603 inflateEnd(&amp;z);
604 return ret &gt;= 0;
607 /* eye candy */
608 static int counter = 0;
609 static void progress(int sig)
611 fprintf(stderr, "\r%d", counter);
612 alarm(1);
615 int main(void)
617 /* oversized so we can read the whole buffer in */
618 unsigned char buf[1024*1024];
619 int len;
620 unsigned i, j;
622 signal(SIGALRM, progress);
623 alarm(1);
625 len = read(0, buf, sizeof(buf));
626 for (i = 0; i &lt; len; i++) {
627 unsigned char c = buf[i];
628 for (j = 0; j &lt;= 0xff; j++) {
629 buf[i] = j;
631 counter++;
632 if (try_zlib(buf, len))
633 printf("i=%d, j=%x\n", i, j);
635 buf[i] = c;
638 alarm(0);
639 fprintf(stderr, "\n");
640 return 0;
641 }</pre>
642 </div>
643 </div>
644 <div class="paragraph">
645 <p>I compiled and ran with:</p>
646 </div>
647 <div class="listingblock">
648 <div class="content">
649 <pre> gcc -Wall -Werror -O3 munge.c -o munge -lz
650 ./munge &lt;zlib</pre>
651 </div>
652 </div>
653 <div class="paragraph">
654 <p>There were a few false positives early on (if you write "no data" in the
655 zlib header, zlib thinks it&#8217;s just fine :) ). But I got a hit about
656 halfway through:</p>
657 </div>
658 <div class="listingblock">
659 <div class="content">
660 <pre> i=5642, j=c7</pre>
661 </div>
662 </div>
663 <div class="paragraph">
664 <p>I let it run to completion, and got a few more hits at the end (where it
665 was munging the CRC to match our broken data). So there was a good
666 chance this middle hit was the source of the problem.</p>
667 </div>
668 <div class="paragraph">
669 <p>I confirmed by tweaking the byte in a hex editor, zlib inflating the
670 result (no errors!), and then piping the output into "git hash-object",
671 which reported the sha1 of the broken object. Success!</p>
672 </div>
673 <div class="paragraph">
674 <p>I fixed the packfile itself with:</p>
675 </div>
676 <div class="listingblock">
677 <div class="content">
678 <pre> chmod +w $pack
679 printf '\xc7' | dd of=$pack bs=1 seek=51659518 conv=notrunc
680 chmod -w $pack</pre>
681 </div>
682 </div>
683 <div class="paragraph">
684 <p>The <code>\xc7</code> comes from the replacement byte our "munge" program found.
685 The offset 51659518 is derived by taking the original object offset
686 (51653873), adding the replacement offset found by "munge" (5642), and
687 then adding back in the 3 bytes of git header we stripped.</p>
688 </div>
689 <div class="paragraph">
690 <p>After that, "git fsck" ran clean.</p>
691 </div>
692 <div class="paragraph">
693 <p>As for the corruption itself, I was lucky that it was indeed a single
694 byte. In fact, it turned out to be a single bit. The byte 0xc7 was
695 corrupted to 0xc5. So presumably it was caused by faulty hardware, or a
696 cosmic ray.</p>
697 </div>
698 <div class="paragraph">
699 <p>And the aborted attempt to look at the inflated output to see what was
700 wrong? I could have looked forever and never found it. Here&#8217;s the diff
701 between what the corrupted data inflates to, versus the real data:</p>
702 </div>
703 <div class="listingblock">
704 <div class="content">
705 <pre> - cp = strtok (arg, "+");
706 + cp = strtok (arg, ".");</pre>
707 </div>
708 </div>
709 <div class="paragraph">
710 <p>It tweaked one byte and still ended up as valid, readable C that just
711 happened to do something totally different! One takeaway is that on a
712 less unlucky day, looking at the zlib output might have actually been
713 helpful, as most random changes would actually break the C code.</p>
714 </div>
715 <div class="paragraph">
716 <p>But more importantly, git&#8217;s hashing and checksumming noticed a problem
717 that easily could have gone undetected in another system. The result
718 still compiled, but would have caused an interesting bug (that would
719 have been blamed on some random commit).</p>
720 </div>
721 </div>
722 </div>
723 <div class="sect1">
724 <h2 id="_the_adventure_continues">The adventure continues&#8230;&#8203;</h2>
725 <div class="sectionbody">
726 <div class="paragraph">
727 <p>I ended up doing this again! Same entity, new hardware. The assumption
728 at this point is that the old disk corrupted the packfile, and then the
729 corruption was migrated to the new hardware (because it was done by
730 rsync or similar, and no fsck was done at the time of migration).</p>
731 </div>
732 <div class="paragraph">
733 <p>This time, the affected blob was over 20 megabytes, which was far too
734 large to do a brute-force on. I followed the instructions above to
735 create the <code>zlib</code> file. I then used the <code>inflate</code> program below to pull
736 the corrupted data from that. Examining that output gave me a hint about
737 where in the file the corruption was. But now I was working with the
738 file itself, not the zlib contents. So knowing the sha1 of the object
739 and the approximate area of the corruption, I used the <code>sha1-munge</code>
740 program below to brute-force the correct byte.</p>
741 </div>
742 <div class="paragraph">
743 <p>Here&#8217;s the inflate program (it&#8217;s essentially <code>gunzip</code> but without the
744 <code>.gz</code> header processing):</p>
745 </div>
746 <div class="listingblock">
747 <div class="content">
748 <pre>#include &lt;stdio.h&gt;
749 #include &lt;string.h&gt;
750 #include &lt;zlib.h&gt;
751 #include &lt;stdlib.h&gt;
753 int main(int argc, char **argv)
756 * oversized so we can read the whole buffer in;
757 * this could actually be switched to streaming
758 * to avoid any memory limitations
760 static unsigned char buf[25 * 1024 * 1024];
761 static unsigned char out[25 * 1024 * 1024];
762 int len;
763 z_stream z;
764 int ret;
766 len = read(0, buf, sizeof(buf));
767 memset(&amp;z, 0, sizeof(z));
768 inflateInit(&amp;z);
770 z.next_in = buf;
771 z.avail_in = len;
772 z.next_out = out;
773 z.avail_out = sizeof(out);
775 ret = inflate(&amp;z, 0);
776 if (ret != Z_OK &amp;&amp; ret != Z_STREAM_END)
777 fprintf(stderr, "initial inflate failed (%d)\n", ret);
779 fprintf(stderr, "outputting %lu bytes", z.total_out);
780 fwrite(out, 1, z.total_out, stdout);
781 return 0;
782 }</pre>
783 </div>
784 </div>
785 <div class="paragraph">
786 <p>And here is the <code>sha1-munge</code> program:</p>
787 </div>
788 <div class="listingblock">
789 <div class="content">
790 <pre>#include &lt;stdio.h&gt;
791 #include &lt;unistd.h&gt;
792 #include &lt;string.h&gt;
793 #include &lt;signal.h&gt;
794 #include &lt;openssl/sha.h&gt;
795 #include &lt;stdlib.h&gt;
797 /* eye candy */
798 static int counter = 0;
799 static void progress(int sig)
801 fprintf(stderr, "\r%d", counter);
802 alarm(1);
805 static const signed char hexval_table[256] = {
806 -1, -1, -1, -1, -1, -1, -1, -1, /* 00-07 */
807 -1, -1, -1, -1, -1, -1, -1, -1, /* 08-0f */
808 -1, -1, -1, -1, -1, -1, -1, -1, /* 10-17 */
809 -1, -1, -1, -1, -1, -1, -1, -1, /* 18-1f */
810 -1, -1, -1, -1, -1, -1, -1, -1, /* 20-27 */
811 -1, -1, -1, -1, -1, -1, -1, -1, /* 28-2f */
812 0, 1, 2, 3, 4, 5, 6, 7, /* 30-37 */
813 8, 9, -1, -1, -1, -1, -1, -1, /* 38-3f */
814 -1, 10, 11, 12, 13, 14, 15, -1, /* 40-47 */
815 -1, -1, -1, -1, -1, -1, -1, -1, /* 48-4f */
816 -1, -1, -1, -1, -1, -1, -1, -1, /* 50-57 */
817 -1, -1, -1, -1, -1, -1, -1, -1, /* 58-5f */
818 -1, 10, 11, 12, 13, 14, 15, -1, /* 60-67 */
819 -1, -1, -1, -1, -1, -1, -1, -1, /* 68-67 */
820 -1, -1, -1, -1, -1, -1, -1, -1, /* 70-77 */
821 -1, -1, -1, -1, -1, -1, -1, -1, /* 78-7f */
822 -1, -1, -1, -1, -1, -1, -1, -1, /* 80-87 */
823 -1, -1, -1, -1, -1, -1, -1, -1, /* 88-8f */
824 -1, -1, -1, -1, -1, -1, -1, -1, /* 90-97 */
825 -1, -1, -1, -1, -1, -1, -1, -1, /* 98-9f */
826 -1, -1, -1, -1, -1, -1, -1, -1, /* a0-a7 */
827 -1, -1, -1, -1, -1, -1, -1, -1, /* a8-af */
828 -1, -1, -1, -1, -1, -1, -1, -1, /* b0-b7 */
829 -1, -1, -1, -1, -1, -1, -1, -1, /* b8-bf */
830 -1, -1, -1, -1, -1, -1, -1, -1, /* c0-c7 */
831 -1, -1, -1, -1, -1, -1, -1, -1, /* c8-cf */
832 -1, -1, -1, -1, -1, -1, -1, -1, /* d0-d7 */
833 -1, -1, -1, -1, -1, -1, -1, -1, /* d8-df */
834 -1, -1, -1, -1, -1, -1, -1, -1, /* e0-e7 */
835 -1, -1, -1, -1, -1, -1, -1, -1, /* e8-ef */
836 -1, -1, -1, -1, -1, -1, -1, -1, /* f0-f7 */
837 -1, -1, -1, -1, -1, -1, -1, -1, /* f8-ff */
840 static inline unsigned int hexval(unsigned char c)
842 return hexval_table[c];
845 static int get_sha1_hex(const char *hex, unsigned char *sha1)
847 int i;
848 for (i = 0; i &lt; 20; i++) {
849 unsigned int val;
851 * hex[1]=='\0' is caught when val is checked below,
852 * but if hex[0] is NUL we have to avoid reading
853 * past the end of the string:
855 if (!hex[0])
856 return -1;
857 val = (hexval(hex[0]) &lt;&lt; 4) | hexval(hex[1]);
858 if (val &amp; ~0xff)
859 return -1;
860 *sha1++ = val;
861 hex += 2;
863 return 0;
866 int main(int argc, char **argv)
868 /* oversized so we can read the whole buffer in */
869 static unsigned char buf[25 * 1024 * 1024];
870 char header[32];
871 int header_len;
872 unsigned char have[20], want[20];
873 int start, len;
874 SHA_CTX orig;
875 unsigned i, j;
877 if (!argv[1] || get_sha1_hex(argv[1], want)) {
878 fprintf(stderr, "usage: sha1-munge &lt;sha1&gt; [start] &lt;file.in\n");
879 return 1;
882 if (argv[2])
883 start = atoi(argv[2]);
884 else
885 start = 0;
887 len = read(0, buf, sizeof(buf));
888 header_len = sprintf(header, "blob %d", len) + 1;
889 fprintf(stderr, "using header: %s\n", header);
892 * We keep a running sha1 so that if you are munging
893 * near the end of the file, we do not have to re-sha1
894 * the unchanged earlier bytes
896 SHA1_Init(&amp;orig);
897 SHA1_Update(&amp;orig, header, header_len);
898 if (start)
899 SHA1_Update(&amp;orig, buf, start);
901 signal(SIGALRM, progress);
902 alarm(1);
904 for (i = start; i &lt; len; i++) {
905 unsigned char c;
906 SHA_CTX x;
908 #if 0
910 * deletion -- this would not actually work in practice,
911 * I think, because we've already committed to a
912 * particular size in the header. Ditto for addition
913 * below. In those cases, you'd have to do the whole
914 * sha1 from scratch, or possibly keep three running
915 * "orig" sha1 computations going.
917 memcpy(&amp;x, &amp;orig, sizeof(x));
918 SHA1_Update(&amp;x, buf + i + 1, len - i - 1);
919 SHA1_Final(have, &amp;x);
920 if (!memcmp(have, want, 20))
921 printf("i=%d, deletion\n", i);
922 #endif
925 * replacement -- note that this tries each of the 256
926 * possible bytes. If you suspect a single-bit flip,
927 * it would be much shorter to just try the 8
928 * bit-flipped variants.
930 c = buf[i];
931 for (j = 0; j &lt;= 0xff; j++) {
932 buf[i] = j;
934 memcpy(&amp;x, &amp;orig, sizeof(x));
935 SHA1_Update(&amp;x, buf + i, len - i);
936 SHA1_Final(have, &amp;x);
937 if (!memcmp(have, want, 20))
938 printf("i=%d, j=%02x\n", i, j);
940 buf[i] = c;
942 #if 0
943 /* addition */
944 for (j = 0; j &lt;= 0xff; j++) {
945 unsigned char extra = j;
946 memcpy(&amp;x, &amp;orig, sizeof(x));
947 SHA1_Update(&amp;x, &amp;extra, 1);
948 SHA1_Update(&amp;x, buf + i, len - i);
949 SHA1_Final(have, &amp;x);
950 if (!memcmp(have, want, 20))
951 printf("i=%d, addition=%02x", i, j);
953 #endif
955 SHA1_Update(&amp;orig, buf + i, 1);
956 counter++;
959 alarm(0);
960 fprintf(stderr, "\r%d\n", counter);
961 return 0;
962 }</pre>
963 </div>
964 </div>
965 </div>
966 </div>
967 </div>
968 <div id="footer">
969 <div id="footer-text">
970 Last updated 2024-08-23 09:48:46 -0700
971 </div>
972 </div>
973 </body>
974 </html>