Commit graph

180 commits

Author SHA1 Message Date
Timo Tijhof
9e9bedf18d exception: Remove ErrorException workaround in handleFatalError()
Follows-up 115df551f2 and its CR (Gerrit I664bfe55359aadb343ee7).

The comment was out of date.

* The stack is indeed unwound at this point for most use cases,
  but using debug_backtrace() doesn't help that.
  What debug_backtrace sees as the same as '(new Exception)->getTrace()'.

  The reason the code used debug_backtrace isn't to obtain a better
  trace. It was using that because HHVM gave us a magic non-standard
  '$trace' parameter into the callback. Given there is no way to
  construct the built-in Exception object with a custom trace,
  the only way we could log it was to build the rest of the array
  ourselves as well. We'd fallback for PHP 5 by back-filling only
  the trace part using debug_backtrace().

  The code for HHVM has been removed meanwhile (d1679955b4).
  What's left is standard ErrorException handling, which our
  Monolog layer should be formatting instead, not duplicated
  here.

Getting a trace here would be nice, but is out of scope for this
change. Assuming the php-wmerrors handler (php7-fatal-error.php
at WMF) sees the stack, that's where we'll get it for prod.
Within MW core under plain PHP 7 there simply isn't a way to get
it, hence php-wmerrors exists (covered in more detail at T187147,
specifically T187147#5165179).

Bug: T233342
Change-Id: Ic81076a8fd1a593460528162d4319fdedb985f30
2019-12-12 00:59:26 +00:00
Umherirrender
0688dd7c6d Set method visibility for various constructors
Change-Id: Id3c88257e866923b06e878ccdeddded7f08f2c98
2019-12-03 20:17:30 +01:00
jenkins-bot
2ad86e787e Merge "exception: Log fatal exception data as 'exception' instead of 'fatal_exception'" 2019-11-23 20:44:43 +00:00
Umherirrender
337ecb0514 Add missing @param and @return to documentation
Change-Id: Ibc5849cc8ea7e7c4eb30ded9c1cfa5f52187c377
2019-11-10 22:12:58 +00:00
Timo Tijhof
115df551f2 exception: Log fatal exception data as 'exception' instead of 'fatal_exception'
This make it easier to write queries in Logstash given the limited
capabilities of its user interface, so that filters for 'exception.trace'
will also match those of fatal errors.

This has gotten even more confusing in the last week because the fatal
errors logged by /etc/php/php7-fatal-error.php in production did use
'exception.trace' already and that means that the same exact exception
(e.g. "Allowed memory … exhausted" and "Maximum execution time … exceeded")
would sometimes be under 'fatal_exception' and sometimes under 'exception'.

Bug: T233342
Change-Id: I664bfe55359aadb343ee742f59af5f26f4c19339
2019-11-07 17:00:51 -05:00
Max Semenik
f1c9cf8879 Minor cleanups
* Identifier case
* Returning a void function result
* Unused variable
* Missing documentation

Change-Id: Ibfd2fc5ae1d91c7c9c6a34bcd4523384d3bca576
2019-11-03 17:10:23 -08:00
Thalia
538d333167 Allow user, language and IP to be passed to UserBlockedError
Accept these objects as params to the UserBlockedError constructor,
since they are used to make the block error message. Pass them from
SpecialPages, Actions and EditPage.

If a caller does not pass all of these params, get them from the
global context as before.

Bug: T234406
Change-Id: Ie8ef047d2710c523b67bfc54fa2ad70fc47c5236
2019-10-17 15:19:28 +01:00
James D. Forrester
c5cc18a740 PHPVersionCheck: Simplify warning as part of dropping HHVM support
Bug: T192166
Change-Id: Ia92b881a7eeab4b8b53531136fb0dbafb6ec30ba
2019-10-10 18:15:48 -07:00
Thalia
df20197250 Introduce a formatter service for block errors
The main reasons for adding this service layer are:
* It allows error messages to be more consistent, by defining
  a set of reportable information that can describe any block
  type and is consistently formatted.
* It decouples formatting from the block classes, removing
  their dependency on language, for the most part.

The service provides one public method, getMessage, which
returns a Message object whose key and parameters are
determined by the type of block. This should be used instead
of the deprecated AbstractBlock::getPermissionsError and
AbstractBlock::getBlockErrorParams.

Calls to AbstractBlock::getPermissionsError are replaced in
this patch.

Bug: T227174
Change-Id: I8caae7e30a46ef7120a86a4e5e6f30ae00855063
2019-10-08 12:29:23 +01:00
jenkins-bot
42f58ae012 Merge "Setup: Move wgArticlePath validation to its main consumer (PathRouter)" 2019-10-07 21:58:16 +00:00
Máté Szabó
d1679955b4 MWExceptionHandler: Remove HHVM-specific behavior
With the removal of HHVM support, we can remove HHVM-specific error
handling from MWExceptionHandler.

* Remove references to HHVM from comments.
* Remove references to PHP 7/PHP 7+ from comments, as we now require
  PHP 7+.
* Remove support for the HHVM-exclusive $trace parameter from
  MWExceptionHandler::handleFatalError().
* Remove HHVM-specific regex when checking if the current error
  is a class not found error.
* Remove delegation to MWExceptionHandler::handleFatalError() from
  MWExceptionHandler::handleError(), as it was only used for HHVM
  fatals when running in PHP 5 mode.
* Remove MWExceptionHandler::$handledFatalCallback that was protecting
  against running MWExceptionHandler::handleFatalError() twice, since this
  could only happen if MWExceptionHandler::handleError() called
  MWExceptionHandler::handleFatalError().
* Remove HHVM's FATAL_ERROR constant from MWExceptionHandler::$fatalErrorTypes.

Change-Id: I110f7195c3094e761264d382f3a26e9a425bb8ad
2019-10-07 02:16:48 +02:00
Aaron Schulz
4f11b61454 Avoid using "enqueue" mode for deferred updates in doPostOutputShutdown
Set appropriate headers and flush the output as needed to avoid blocking
the client on post-send updates for the stock apache2 server scenario.
Several cases have bits of header logic to avoid delay:

a) basic GET/POST requests that succeed (e.g. HTTP 2XX)
b) requests that fail with errors (e.g. HTTP 500)
c) If-Modified-Since requests (e.g. HTTP 304)
d) HEAD requests

This last two still block on deferred updates, so schedulePostSendJobs()
does not trigger on them as a form of mitigation. Slow deferred updates
should only trigger on POST anyway (inline and redirect responses are
OK), so this should not be much of a problem.

Deprecate triggerJobs() and implement post-send job runs as a deferred.
This makes it easy to check for the existence of post-send updates by
calling DeferredUpdates::pendingUpdatesCount() after the pre-send stage.
Also, avoid running jobs on requests that had exceptions. Relatedly,
remove $mode option from restInPeace() and doPostOutputShutdown()
Only one caller was using the non-default options.

Bug: T206283
Change-Id: I2dd2b71f1ced0f4ef8b16ff41ffb23bb5b4c7028
2019-09-30 22:59:59 +00:00
Timo Tijhof
11e3172c03 exception: Let MediaWiki.php control final output for ErrorPageError
The same way it does already for non-error output. This makes
it so that doPreOutputCommit() consistently happens between
the staging of output and the actual sending of output.

It is still allowed for code to bypass this, such as for fatal
errors and for handlers that disable OutputPage (like Special:Export).

But for cases where we do want to perform doPreOutputCommit(), it
should be run consistently between staging and sending so that it
can make appropiate decisions based on the current state of
OutputPage.

Previously, the state of OutputPage seen by doPreOutputCommit()
would be the broken/incomplete output of a seemingly succesful
(possibly cacheable) user action, which would then, after
doPreOutputCommit() runs, be completely replaced by $e->report()/
$out->showErrorPage().

This is a prerequisite for being able to reliably send cookie-block
cookies on error pages (next patch).

Bug: T233594
Change-Id: Iaeaf5e55a5868e6be534ddda73f3b56b9d6ef8f0
2019-09-26 07:56:14 +00:00
Timo Tijhof
480b7341f8 Setup: Move wgArticlePath validation to its main consumer (PathRouter)
The variable is also read in a few other places, such as to
export the value from api.php (siteinfo) and load.php (mw.config)
but those requests don't need to be held back by this extra
logic.

Alternatively, if we really want to require this for all consumption,
we should probably let PathRouter provide the value and require
consumers to use it. E.g. services->getPathRouter->getArticlePath,
or something like that.

As easy first step, I'm moving it to PathRouter, called from
WebRequest::getPathInfo which is still called on all index.php
requests for any wiki page action in any namespace (incl Special)
when the wiki uses anything other than the default 'index.php?title='
article path.

Test Plan:
* Set '$wgArticlePath = 'bla';`
* View /mediawiki/index.php/Main_Page, and observe the fatal
  error message (same as before this change).

Bug: T189966
Change-Id: Id06c2557e2addb58faeef0b6f7767a65b8de55a5
2019-09-25 23:06:52 +00:00
Timo Tijhof
ebee381c23 exception: Add missing early return for UserNotLoggedIn error page
Follows-up d0439af89f.

If the UserNotLoggedIn class is constructed with an unsupported
message parameter, thrown, and handled by MWExceptionHandler, the
report() method would get called, and it would call the parent,
which stages a full error page and sends it via OutputPage::output.

Due to the missing return statement, it would then still execute
the remaining code, which messes up the internal state of the
already-sent OutputPage object by changing its redirect target
(which will never be used, but might confuse other consumers),
and trying to re-send output() and redirect headers, which will
fail with a warning.

Fixing this is required for T233594 and Iaeaf5e55a586, which allows
ErrorPageError to be "stage only" without ending output. Without
this fix, it would call the parent and do stage-only, but then
the remaining code in this method also work and actually succeed
at sending an invalid message to the user.

To preserve current (accidentally correct) behaviour, this needs
to be fixed first.

Bug: T233594
Bug: T17484
Change-Id: Ic5d73becd889839399a5b425cbbe22a3401acea9
2019-09-24 00:33:20 +01:00
Daimona Eaytoy
b138a9b228 Fix using null for a non-nullable argument
These are reported by phan as PhanTypeMismatchArgumentNullableInternal
when null_casts_as_any_type is disabled.

Change-Id: I85076ee31c1bfc59a19600e84da0d915e425890a
2019-09-19 16:55:03 +00:00
Gergő Tisza
59e461136d
Allow logging arbitrary extra data in MWExceptionHandler::logException
Change-Id: I8215191900fa3a61d6e9c80bbe36c83c8be1710a
2019-09-12 17:19:07 +02:00
Umherirrender
54190757bb Unpack arrays on variadic arguments
This avoids extra handling in the function to unpack an array

Change-Id: I93277599bc8125e23fca53d43a728fb7e9e39aad
2019-08-31 23:23:50 +00:00
Petr Pchelko
acaa3e3136 Remove deprecated User groups/permission static calls.
Bug: T220191
Change-Id: Ifa8afa90c432723b0bba0033a46b6a499c77e6fc
2019-08-21 19:42:01 -07:00
Reedy
9f2ffdfbd4 Remove "Squiz.WhiteSpace.FunctionSpacing" from phpcs exclusions
Change-Id: I78b3315f26ab91b6b443f5b028a635552f82f5a3
2019-05-11 02:44:26 +01:00
Thalia
824655f3b7 Separate Block into AbstractBlock, Block and SystemBlock
This commit splits the existing Block class into AbstractBlock, Block
and SystemBlock.

Before this patch, the Block class represents several types of
blocks, which can be separated into blocks stored in the database,
and temporary blocks created by the system. These are now
represented by Block and SystemBlock, which inherit from
AbstractBlock.

This lays the foundations for:
* enforcing block parameters from multiple blocks that apply to a
user/IP address
* improvements to the Block API, including the addition of services

Breaking changes: functions expecting a Block object should still
expect a Block object if it came from the database, but other
functions may now need to expect an AbstractBlock or SystemBlock
object. (Note that an alternative naming scheme, in which the
abstract class is called Block and the subclasses are DatabaseBlock
and SystemBlock, avoids this breakage. However, it introduces more
breakages to calls to static Block methods and new Block
instantiations.)

Changes to tests: system blocks don't set the $blockCreateAccount or
$mExipry block properties, so remove/change any tests that assume
they do.

Bug: T222737
Change-Id: I83bceb5e5049e254c90ace060f8f8fad44696c67
2019-05-07 17:36:31 -05:00
Timo Tijhof
977e58e82e exception: Document the three ways we listen for errors/fatals/exceptions
It is now clear to me why most fatals are logged to 'exception'
on PHP 7, instead of 'fatal' (as on HHVM). It is because these
are, as of PHP 7, technically recoverable if caught locally
with 'catch (Throwable)', and as such should no longer be classified
as 'fatal'. I suppose that's fine and something we'll get used to.

The most important distinction to keep is between 'error' and 'fatal/exception'
given the latter is more heavily monitored and alerted on, but
otherwise they are not usually distingished in query, we treat
them equal for the most part.

Bug: T187147
Change-Id: I64bf0b32dd2648cf72297bdc294e315375329a4d
2019-05-07 18:54:52 +01:00
Aryeh Gregor
7b4489e019 Get rid of unnecessary func_get_args() and friends
HHVM does not support variadic arguments with type hints.  This is
mostly not a big problem, because we can just drop the type hint, but
for some reason PHPUnit adds a type hint of "array" when it creates
mocks, so a class with a variadic method can't be mocked (at least in
some cases).  As such, I left alone all the classes that seem like
someone might like to mock them, like Title and User.  If anyone wants
to mock them in the future, they'll have to switch back to
func_get_args().  Some of the changes are definitely safe, like
functions and test classes.

In most cases, func_get_args() (and/or func_get_arg(), func_num_args() )
were only present because the code was written before we required PHP
5.6, and writing them as variadic functions is strictly superior. In
some cases I left them alone, aside from HHVM compatibility:

* Forwarding all arguments to another function. It's useful to keep
  func_get_args() here where we want to keep the list of expected
  arguments and their meanings in the function signature line for
  documentation purposes, but don't want to copy-paste a long line of
  argument names.
* Handling deprecated calling conventions.
* One or two miscellaneous cases where we're basically using the
  arguments individually but want to use them as an array as well for
  some reason.

Change-Id: I066ec95a7beb7c0665146195a08e7cce1222c788
2019-04-12 20:17:01 +00:00
Reedy
c13fee87d4 Collapse some nested if statements
Change-Id: I9a97325d738d09370d29d35d5254bc0dadc57ff4
2019-04-04 19:02:22 +00:00
Brian Wolff
d5dd48b8a6 Various fixes to make phan-taint-check happier
Bug: T216348
Change-Id: Ice672eed3b7e4a199e1307a6477ffe31502b97b5
2019-03-02 23:49:24 +00:00
James D. Forrester
0a3217462c Drop MWExceptionHandler::getLogId(), deprecated in 1.27 and unused
Change-Id: Id03aaf4f2ea5c910e13274826e44033e12adcd2e
2019-02-09 07:54:58 +00:00
Umherirrender
5d2e39401d Move interface ILocalizedException to own file
Change-Id: I66429a89633a74a22999775214aa23ae189b837e
2019-02-01 20:05:30 +01:00
Thiemo Kreuz
c3dfa88966 Add missing empty lines between methods
This might hint at an edge-case in the PHP CodeSniffer sniff that should
detect if methods are separated by a single empty line. Feel free to
investigate. I, personally, can't invest more time in this than
suggesting this quick fix.

Change-Id: Ib3c60eac76f255b4fe929f7933de256222716576
2019-01-15 19:14:35 +00:00
Jakub Vrana
0d3d79ae83 Do not pass unused parameter
Found by PHPStan.

Change-Id: I4a73279b6956b9819e609536ae6774872f1736f4
2018-12-01 18:09:58 +01:00
Juan Osorio
1d930860cc Removes Google web search from exception page
When a wiki is down, it is not necessarily useful to be able to
search the web. Additionally, there is general consensus that
the hard-coded Google search form should be removed.

Bug: T208871
Change-Id: I5bcae848de1144d4fc1116c475b2e2ab1ccc3f7d
2018-11-13 15:47:42 +00:00
James D. Forrester
36ec0c6984 Drop six authentication-related hooks, deprecated in 1.27
AbortAutoAccount, AbortNewAccount, AbortLogin, LoginUserMigrated,
UserCreateForm, and UserLoginForm are all unused in Wikimedia
production and rare in other extensions.

This also scraps the FakeAuthTemplate and LoginForm classes and
the occasional remainig references thereto.

Bug: T193755
Change-Id: I24d6fa963f402d4311fa00fc11536a37ee3bd31e
2018-10-29 15:02:06 -07:00
Timo Tijhof
1f92231f81 exception: Correct label "Notice" for E_USER_NOTICE, not "Warning"
Follows-up ef06b528d9, which fixed the severity of all PHP errors
to have severity "Warning" or higher.

However, it also accidentally changed the label of "Notice"
to "Warning", which is confusing and incorrect.

Change-Id: Iffd39aa23b7f2cbff5cdaf876b8d4d595dcd6f96
2018-10-12 05:05:16 +01:00
Fomafix
1472f02b36 Phabricator: Use Tddddd instead of Bug ddddd in comments
Change-Id: Ic9fe03cab270bd6be738af346164ad5d31a0d780
2018-10-04 09:15:02 +02:00
Timo Tijhof
9512ebe736 exception: Add FIXME about code duplication
These methods aren't identical, so consolidation isn't
immediately obvious, and creating dependencies is problematic
in error handling code given there is a lot of pressure on this
code to not by itself cause additional errors.

This means that maybe it's best to keep these inlined without
duplication, but at the very least we then need to remember
to keep these in sync. This duplication has been around for
a while now, but documentation can never come too late...

Change-Id: I60160f61c13c8e115d839acce222f110e30bc2f2
2018-09-28 22:17:07 +00:00
Timo Tijhof
c8ca57f903 exception: Report uncaught "Catchable" fatal to "fatal" channel
Things like "Catchable fatal error: Must be X, null given" stop
execution immediately after the error handler callback, and produce
an HTTP 500 Internal Server Error page. They are very fatal.

Per <https://secure.php.net/manual/en/language.errors.php7.php>,
on PHP 7 this results in a TypeError throwable which will
eventually fatal the request and be reported through
set_exception_handler, or be caught by our top-level 'catch'
and artificially forwarded to our set_exception_handler callback.

On HHVM, these fatal error types are PHP5-like in that they
don't have a throwable object to throw yet, instead the error
meta-data is sent directly as parameeters to set_error_handler,
the same as for warnings. We need to intercept them there so
that they are reported correctly.

Sample from PHP 7:

> MediaWiki\Storage\MutableRevisionRecord::newFromParentRevision( null );
> [no req]   TypeError from line 50 of .../MutableRevisionRecord.php:
> Argument 1 passed to ...\MutableRevisionRecord::newFromParentRevision()
> must be an instance of MediaWiki\Storage\RevisionRecord, null given,
> called in /var/www/mediawiki/maintenance/eval.php(78) ...

[exit status: error(255)]

Sample from HHVM:

> MediaWiki\Storage\MutableRevisionRecord::newFromParentRevision( null );
> [hphp] set_error_handler called with:
> ...  $type = 4096 // E_RECOVERABLE_ERROR
>
> [hphp] [...] Catchable fatal error:
> Argument 1 passed to ...\MutableRevisionRecord::newFromParentRevision()
> must be an instance of MediaWiki\Storage\RevisionRecord, null given
> ...

[exit status: error(255)]

Interestingly, if you forget to return false from set_error_handler
for fatal errors on HHVM, it can actually continue execution.

Bug: T205677
Change-Id: I18dd2ff37fa2c2679d0c598cbeff0c61c2fe0253
2018-09-28 00:43:22 +00:00
Timo Tijhof
8476ec3cb8 exception: Avoid preg_replace for literal swap
Follows-up bbcbcaba3d.

Change-Id: Ie7b76c28ba53668d73a8435c4d2ec91757bd2372
2018-09-27 17:39:42 +01:00
jenkins-bot
32d29b4a68 Merge "Fix html <title> for exceptions during message parsing." 2018-09-13 03:34:52 +00:00
Timo Tijhof
ef06b528d9 exception: Do not log PHP errors with severity DEBUG or INFO
All PHP errors should be considered by monitoring queries
and error-rate alerts.

Levels DEBUG and INFO are for manual entries that can help in
debugging to see what path a program went down or what the
circumstances were in that code.

There is no reason to spread PHP error-types out on the full range
of PSR-3's DEBUG to ERROR spectrum. Instead, keep it within either
WARNING or ERROR, not below it.

Change-Id: I3f35a519b50aef5b93b9ab7a89a7c3e11d70681f
2018-09-06 03:42:09 +01:00
Brian Wolff
bbcbcaba3d Fix html <title> for exceptions during message parsing.
Previously an ugly {{SITENAME}} would show up for exceptions
that happened in the middle of processing a message

Change-Id: I4e3b675673dc3b74f89e4325f6a0a8b44162f478
2018-09-01 20:19:45 +00:00
Bill Pirkle
807125abdb Deprecate $wgShowSQLErrors and $wgShowDBErrorBacktrace and make nonfunctional
Clarify and simplify exception output by deprecating
$wgShowSQLErrors and wgShowDBErrorBacktrace.
$wgShowExceptionDetails will now control most related output.
$wgShowHostnames will now solely control output of
MWExceptionRenderer::reportOutageHTML.

Bug: T165768
Change-Id: Idead2c11c499463dfa6293c3d4b33be3bde92e1a
2018-07-25 10:38:19 -05:00
Umherirrender
130ec2523d Fix PhanTypeMismatchDeclaredParam
Auto fix MediaWiki.Commenting.FunctionComment.DefaultNullTypeParam sniff

Change-Id: I865323fd0295aabd06f3e3c75e0e5043fb31069e
2018-07-07 00:34:30 +00:00
jenkins-bot
f459a71f75 Merge "MWExceptionRenderer: Fix db error outage page" 2018-06-24 02:22:09 +00:00
Strainu
94b58b2c26 MWExceptionRenderer: Fix db error outage page
Set content encoding and add some content to the header tag.

Bug: T195525
Change-Id: Ieabfe18280359459e9462204371d3fe8d62a4177
2018-06-15 22:21:16 +02:00
Max Semenik
6e956d55aa Replace call_user_func_array(), part 2
Uses new PHP 5.6 syntax like ...parameter unpacking and
calling anything looking like a callback to make the code more readable.
There are much more occurrences but this commit is intentionally limited
to an easily reviewable size.

In one occurrence, a simple conditional instead of trickery was much more readable.

This patch finishes all the easy stuf in the core, the remainder is either unobvious
or would result in smaller readability gains. It will be carefully dealt with in
further commits.

Change-Id: I79a16c48bfb98b75e5b99f2f6f4fa07b3ae02c5b
2018-06-07 20:19:26 -07:00
Gergő Tisza
8ee55867c6 exception: Improve formatting of fatal error log messages
Use human-readable stack trace instead of array dump,
try to display the URL and the request ID, use the same
message format as exceptions,

Bug: T189851
Change-Id: I3edf2dbd5639ceecc668719c065ecdce33157ff5
2018-03-21 19:27:12 +00:00
Brad Jorsch
27c61fb1e9 Add actor table and code to start using it
Storing the user name or IP in every row in large tables like revision
and logging takes up space and makes operations on these tables slower.
This patch begins the process of moving those into one "actor" table
which other tables can reference with a single integer field.

A subsequent patch will remove the old columns.

Bug: T167246
Depends-On: I9293fd6e0f958d87e52965de925046f1bb8f8a50
Change-Id: I8d825eb02c69cc66d90bd41325133fd3f99f0226
2018-02-23 10:06:20 -08:00
Brad Jorsch
4a275ea53c Don't write exceptions to STDERR from BadTitleErrorTest or ThrottledErrorTest
It's annoying and pointless. Instead, have MWException write them to
standard output where we can catch them with ob_start().

Bug: T170028
Bug: T170029
Change-Id: Icd99c1c39d4a30d78c511d33948ef639e1b92455
2018-02-16 09:01:51 +00:00
Reedy
39f0f919c5 Update suppressWarning()/restoreWarning() calls
Bug: T182273
Change-Id: I9e1b628fe5949ca54258424c2e45b2fb6d491d0f
2018-02-10 08:50:12 +00:00
Gergő Tisza
87a8c1de73
Make it possible to not propagate errors to PHP
Add a $wgPropagateErrors configuration variable which can be used
to prevent passing handled errors to PHP (and thus logging them twice).

Bug: T45086
Change-Id: I64ab09762a04de2007b7d7864e3c504a1d6f8aee
2018-02-08 14:13:54 -08:00
Umherirrender
3124a990a2 Use ::class to resolve class names in includes files
This helps to find renamed or misspelled classes earlier.
Phan will check the class names

Change-Id: I07a925c2a9404b0865e8a8703864ded9d14aa769
2018-01-27 20:34:29 +01:00