Tricky question. Basically, I'd use the "refactoring" method, which I would restate as "if you touch the code, document it".
But to be precise; as issues come up, and as you have to gain familiarity with the code to fix the bugs that occur, I'd say you should use that familiarity to write comments on that code in particular; in essence, the motivation to fix the bug has at that point forced you to gain enough familiarity with the code to be able to document it. And for that reason, I'd be leery of following unrelated branches OR of documenting unrelated functions, because at that point, if you're not performing active testing of the code (to verify your bug fix), then it's hard to be totally certain that you understand precisely what the code does and why. (I'm not getting into the issue that it can also be hard to figure out precisely what and why the code does what it does even when testing a bug fix; you've probably figured that out from your experiences.)
This approach should tend to maximize accuracy, with a sacrifice of overall speed, but not impact your need to maintain the code too severely at the same time. If your bugfixing duties are small, of course, you can venture into "unknown territory" and begin documenting there, but if you (like most of us) can't find enough time in the day to both fix code and document it, this is a good compromise.
One thing bears noting as well; you should have good external documentation. You say that your code doesn't have references to external documentation; I hope for your sake that such external documentation exists, though. If not, I'd actually make writing that external documentation your first priority; something on the level of a functional spec is, I think, absolutely critical to all big software projects. The reason is that functional specs, or high-level documentation of that form, can help prevent "feature creep" or "feature drift" in any software; and feature drift (in particular) can be destructive to documentation as it can cause the documentation to become out-of-date. (I define feature creep as the progressive (and annoying) addition of features to a piece of software; feature drift, on the other hand, is where the set of actions that software takes slowly changes over time. Feature creep is ADDITIVE, i.e. it usually involves increasing the set of functionality of the software; feature drift, on the other hand, is zero-sum; one by one, one piece of edge functionality gets defined to do something different, until the software is doing something completely different than originally intended. Feature drift is rare, but DEADLY for documentation.)