AgeCommit message (Collapse)AuthorLines
Make the early-exit filter meet a closed pipeBryce Kwon-7/+10
The email filter was handed a few bytes, which usually sit in the pipe before the filter has even exited, so a cgit that died of SIGPIPE passed most runs. A source filter handed more than a pipe holds has to see the write fail.
Hold the mailmap to max-blob-sizeBryce Kwon-0/+31
git's read_mailmap_blob inflates the whole blob, so a pusher could make every page of a repository read as much as they liked. git reads a note and the .gitmodules file whole as well, and capping those would mean bounding the lookups where the log, commit and tree pages make them, so the manual names them instead. Nothing tested that mailmap.file and mailmap.blob are ignored either.
Test markup in a scanned repository's own wordsBryce Kwon-0/+26
A scanned repository sets its description, owner and section without trust, and no test gave them any markup.
Test blame on a binary fileBryce Kwon-0/+21
t0104's binary fixture never turns blame on, so neither the blame page's own refusal nor the missing link on the file's page had a test.
Test a HEAD aimed outside its repositoryBryce Kwon-0/+18
The defbranch check had a test while its twin for a crafted HEAD, which the index reads the same way to date a repository, had none.
Pin the robots.txt rulesBryce Kwon-0/+13
Nothing in tests/ read robots.txt, so dropping the trailing slashes again went unnoticed.
Feed the Location header every kind of byteBryce Kwon-0/+13
Only a benign query had been redirected, so nothing showed that a space, a control byte or a byte past ASCII in the query string is encoded before it reaches the Location header.
Test the download names a request choosesBryce Kwon-0/+18
The plain page's header was the only one fed a newline. A snapshot asked for with h= keeps the name it was requested under, and a blob fetched by id takes any path, so both put visitor bytes into Content-Disposition.
Check the empty author on every page it reachesBryce Kwon-9/+22
The title claimed every page, but only the log, commit and atom pages were asked for. The commit now changes a file, since the patch page leaves out a commit with nothing to show, and its parent is read before the printf, where a failed rev-parse would have gone unnoticed.
Test the dumb transport allowlist in one tableBryce Kwon-24/+18
The allowlist was tested in two places, and the 404 alone did not show the transport was live behind the auth filter, since a page that does not exist answers the same. A loose object and HEAD now have to come through, and the planted alternates file is removed even when the test fails, where it used to leave rob borrowing foo's objects.
Ask for the two 404 pages with the cache offBryce Kwon-10/+9
Both requests went through the shared page cache, and the clone one only worked because clone pages are never stored, which is what the cgitrc_copy comment warns of.
Check the order of branches at odd objectsBryce Kwon-14/+27
points-at-tree only ever matched its entry in the branch switcher, and points-at-tag was never looked for. Every branch also shared one date, so the age and name sorts gave the same rows, and nothing showed the name setting had applied. The loose refs written by hand need the files backend.
Read the surplus conversions from their own pageBryce Kwon-6/+3
The check read the page the previous test had left, and it took any hex where the commit goes and only two of the eight conversions.
Try every risky scheme in a .gitmodules urlBryce Kwon-12/+29
Only a lowercase javascript url was tried, so a denylist of that one spelling would have passed. The quote test also read the page the test before it had left.
Test request values a page echoes backBryce Kwon-0/+36
Only %zz%2 had been sent, so nothing showed that markup in the query, the hidden inputs a form carries, the errors naming a refused value or the Host header is escaped on its way back.
Check the lone percent sign in the search boxBryce Kwon-5/+4
For a bare q=% only the status was checked, so a decoder that dropped the sign passed.
Test markup in refs, names and messagesBryce Kwon-0/+54
No test gave a ref name, a commit or tag message, a note or an ident any markup, and the one hostile file name never reached an attribute. html_txt leaves quotes alone, so a name holding both a quote and a bracket is what tells an attribute written as text.
Test the leading slashes stripped from a urlBryce Kwon-0/+16
Nothing showed that every leading slash goes, through url= or PATH_INFO, and one left behind joins the virtual root into a scheme-relative link to another host.
Send the advisory payloads through PATH_INFOBryce Kwon-0/+35
All three shipped server configs hand cgit the path as PATH_INFO, already decoded, yet every hostile path in the tests went through url= instead.
Prove the filter saw the hostile file nameBryce Kwon-5/+4
The name also sits in the breadcrumb and the title, so the test passed with the source filter never run, and the missing marker proved nothing. dump.sh echoes its arguments ahead of the body it upper-cases, which shows the name arrived whole as one argument.
Check the line links of a side-by-side diffBryce Kwon-9/+17
The links have been written through html_attr since b8adfd6, so with the percent-encoding dropped a quote came out as an entity the absence check could not match, and the presence check was met by the file links above the diff. The test now reads the line links themselves, for a name holding a hash and a question mark as well.
Look for inline handlers on every main pageBryce Kwon-4/+15
Only the commit page was checked, and only for onchange, though a site policy without unsafe-inline blocks every inline handler on any page.
Tie each escaped readme to its own payloadBryce Kwon-8/+7
The escaped script tag alone matched either readme, so the markdown page showing the text readme passed.
Compare the small blob the plain page servesBryce Kwon-2/+6
The test took any page holding the word top, with no status checked. The refusal half lives in t0204, so the fixture now says why its limit is set so low.
Read the --output refusal from its own requestBryce Kwon-10/+10
The refusal was read from a page the previous test had left, which --run could skip, and both requests went through the shared page cache. The marker is also named apart from the one the filter test plants, so a failure in one cannot fail the other.
Test every scanned key that waits on trustBryce Kwon-23/+79
Only head-content and logo-link were tried, so logo, clone-url and both module-link forms could have been taken from a repository's own cgitrc unnoticed. A trusted control shows each value would reach the page, and the refused disk readmes are now checked against a file that would show if read.
Check the policy sent with repository bytesBryce Kwon-0/+28
No test asserted the Content-Security-Policy header, though it is all that keeps script in an SVG from running when the plain page serves it under its own type.
Test the snapshot slash rule on a real refBryce Kwon-4/+20
Every candidate name meets check_refname_format first, which refuses the old payload, so the slash rule never answered it and could go unnoticed. A tag holding a slash reaches it, and a name in revision syntax without a slash now pins the ref name check of its own.
Catch an ignored SIGPIPE under any shellBryce Kwon-9/+15
dash reports a write to a closed pipe as an I/O error and never names a broken pipe, so where sh is dash the test passed with the reset removed. The writer now leaves a marker when it outlives the closed pipe, which it can only do with the signal ignored. That holds under dash, bash and ksh.
Prove the login body is cut at the bufferBryce Kwon-5/+16
The posted body was 22 bytes, so an unclamped read stopped at its end and nothing overflowed, and the test could not fail. The filter now counts what it was handed from a body larger than the buffer.
Ask for the working auth pages through cgit_okBryce Kwon-13/+19
The unedited copy and the login page were requested through cgit_rc, so a page cut short or an error logged on the way passed. The owner and description checks on the login page could not fail either if the config lost them, so the same config with a filter that lets the visitor in now has to show both.
Count the auth unit checks as skipped without LuaBryce Kwon-3/+6
With no standalone Lua on the path the unit checks were never registered, so they counted as neither run nor skipped, and t0505 passed on its cgit checks alone.
Say which earlier tests each hook case needsBryce Kwon-2/+6
Push to each hook installed as post-receiveBryce Kwon-0/+35
No hook ran the way git runs it, so the shebang, the executable bit, GIT_DIR, the refs on stdin and the remote: lines a pusher sees were all untested.
Check the commit-graph hook with a git too oldBryce Kwon-0/+24
The header says a git too old for the options leaves the graph as it was and the hook stays silent, but every run had a git that could write it.
Run the hooks under every POSIX shell presentBryce Kwon-24/+45
Only sh, dash, ksh and bash were tried, so busybox sh ran only where it is /bin/sh, and mksh, yash, posh and zsh's sh mode never ran. Where sh is a link to dash, the same shell ran twice. A shell reached by two names now runs once, and the list is said so a run shows what it covered.
Drop cached pages asked for with an escaped urlBryce Kwon-2/+20
README tells a visitor to write a plus in the query form as %2b, and cgit caches such a page under the raw query, but the hook compared that query with the url as it stands. A push to foo+bar.git left its pages under url=foo%2bbar.git/ and r=foo%2Bbar.git cached and stale until their ttl ran out. Decoding in sh would take more than the hook is worth, so a query with a % or a + now counts as stale, which costs another repository's page at most a refill.
Check more of the keys the cache hook readsBryce Kwon-0/+16
No page asked for with r= was cached, no slot held a head that does not parse as cgit's, and the hook never met a cache root that was missing, so ignoring r=, keeping an unreadable slot, or complaining without a cache all passed.
Write the auth test configs through cgitrc_repoBryce Kwon-25/+4
Drive the auth actions through the harnessBryce Kwon-14/+2
run_action repeated harness.run line for line, and three comments only labelled the sections below them.
Check the two auth filters share their codeBryce Kwon-0/+14
Both say a change to the code they share belongs in both, but nothing held them to it, so a fix made to one alone in a path the unit checks do not reach would have gone unseen.
Hold signatures to the length SHA-256 givesBryce Kwon-1/+7
The fake HMAC returned 16 bytes, so the checks signed with signatures half the real length, and a signature cut short passed. tohex's output was never pinned either, so dropping its zero padding stayed consistent with itself and passed.
Check a session cookie scoped below the rootBryce Kwon-0/+9
A cookie_path other than / has to keep Secure but drop the __Host- name, which a browser takes only for the whole host. Neither was tried.
Check expired and planted sessions on a visitBryce Kwon-0/+7
An expired session was only tried against validate_value, never sent through a visit, and nothing sent a session under the plain cookie name, which a sibling subdomain can set where it cannot set the __Host- one.
Check the form is there where a message is notBryce Kwon-1/+4
The checks that a forged session is not taken for a signed-in visitor, and that https brings no warning, would also have passed on the page saying logins are unavailable.
Check a login when crypt cannot check the hashBryce Kwon-1/+12
crypt(3) answers nil for a kind of hash the system does not check, but the stand-in never did, so a login that raised on it, or let it through, passed.
Check that a later push adds a graph layerBryce Kwon-2/+8
The check was a negated test_cmp, which also passes when either file is missing, and a changed chain does not prove the new layer was written. The chain's last line now has to name a graph file that exists and was not in the chain before the push.
Check the cache hook in a non-bare repositoryBryce Kwon-0/+29
scan-path finds such a repository by its .git and serves it at the work tree's path, so the hook has to strip the /.git it runs in. Only bare repositories were tried, and a hook that kept it passed.
Check the cache hook with remove_suffix setBryce Kwon-0/+37
Nothing ran the hook against a cache filled with remove-suffix=1, so a hook that kept the .git on the url, and so dropped none of the pages cgit had cached under the shorter one, passed.
Check that cgit reads what the age hook writesBryce Kwon-0/+6
The hook exists to feed the idle column, but nothing had cgit read an age file, so a hook writing a date cgit cannot parse, or one at a path cgit no longer reads, passed.