From 3603176e77a486acb4d09ff81e40e9d0345f4253 Mon Sep 17 00:00:00 2001
From: Lucas Werkmeister <mail@lucaswerkmeister.de>
Date: Mon, 17 Dec 2018 14:02:39 +0100
Subject: [PATCH] SECURITY: Fix cache mode for (un)patrolled recent changes
 query

Restricting the list of recent changes to patrolled, not patrolled,
autopatrolled, not autopatrolled, or unpatrolled recent changes requires
special permissions (as does displaying that status in the properties of
returned entries), but we only set the cache mode to private in the
first two cases.

Bug: T212118
Change-Id: I4c3fe6e47f80ebf97fa37875c704328d08772d26
---
 includes/api/ApiQueryRecentChanges.php | 29 +++++++++++++++-----------
 1 file changed, 17 insertions(+), 12 deletions(-)

diff --git a/includes/api/ApiQueryRecentChanges.php b/includes/api/ApiQueryRecentChanges.php
index 7c6b4634e5..fe09ce9a01 100644
--- a/includes/api/ApiQueryRecentChanges.php
+++ b/includes/api/ApiQueryRecentChanges.php
@@ -214,12 +214,7 @@ public function run( $resultPageSet = null ) {
 			}
 
 			// Check permissions
-			if ( isset( $show['patrolled'] )
-				|| isset( $show['!patrolled'] )
-				|| isset( $show['unpatrolled'] )
-				|| isset( $show['autopatrolled'] )
-				|| isset( $show['!autopatrolled'] )
-			) {
+			if ( $this->includesPatrollingFlags( $show ) ) {
 				if ( !$user->useRCPatrol() && !$user->useNPPatrol() ) {
 					$this->dieWithError( 'apierror-permissiondenied-patrolflag', 'permissiondenied' );
 				}
@@ -642,13 +637,23 @@ public function extractRowInfo( $row ) {
 		return $vals;
 	}
 
+	/**
+	 * @param array $flagsArray flipped array (string flags are keys)
+	 * @return bool
+	 */
+	private function includesPatrollingFlags( array $flagsArray ) {
+		return isset( $flagsArray['patrolled'] ) ||
+			isset( $flagsArray['!patrolled'] ) ||
+			isset( $flagsArray['unpatrolled'] ) ||
+			isset( $flagsArray['autopatrolled'] ) ||
+			isset( $flagsArray['!autopatrolled'] );
+	}
+
 	public function getCacheMode( $params ) {
-		if ( isset( $params['show'] ) ) {
-			foreach ( $params['show'] as $show ) {
-				if ( $show === 'patrolled' || $show === '!patrolled' ) {
-					return 'private';
-				}
-			}
+		if ( isset( $params['show'] ) &&
+			$this->includesPatrollingFlags( array_flip( $params['show'] ) )
+		) {
+			return 'private';
 		}
 		if ( isset( $params['token'] ) ) {
 			return 'private';
-- 
2.19.1

