diff mbox

[pacman-dev,v2] libmakepkg/lint_pkgbuild: lint depends/etc. as if they are pkgname

Message ID 20180403214814.20305-1-eschwartz@archlinux.org
State Accepted, archived
Headers show

Commit Message

Eli Schwartz April 3, 2018, 9:48 p.m. UTC
depends, provides, conflicts, replaces, and other variables that are
meant to contain package names, are now checked to ensure

1) the name component contains only characters that would equate to
   a valid pkgname.
2) the version component contains only characters that would equate
   to a valid pkgver.
3) comparison operator is a valid comparison operator (e.g. provides
   only allows exact = while optdepends doesn't allow anything)

This also refactors pkgname into a shared utility function, wires up
pkgbase optdepends and provides to use it, and gives pkgver a touchup
to allow referencing where it was called from.

Fixes FS#57833 and a bit of extra.

Signed-off-by: Eli Schwartz <eschwartz@archlinux.org>
---

v2: fix being horribly broken in the case where some provider is not in
fact versioned, and the "$ver" still contains the name. This means if
the name contains chars which are valid in pkgname but not in pkgver the
whole thing collapses. A popular example is pkgname containing a hyphen.

(This still "worked"/passed by accident if the valid pkgname was entirely
alphanumeric, something I did not think to test.)

This check is done like this, because we *want* to spot empty pkgver,
since provides=('foo=') is rightly an issue of an empty pkgver.

 scripts/Makefile.am                                |  4 ++
 .../{provides.sh.in => checkdepends.sh.in}         | 46 ++++++++-----------
 .../{pkgbase.sh.in => conflicts.sh.in}             | 44 ++++++++++--------
 .../lint_pkgbuild/{pkgbase.sh.in => depends.sh.in} | 44 ++++++++++--------
 .../{provides.sh.in => makedepends.sh.in}          | 46 ++++++++-----------
 scripts/libmakepkg/lint_pkgbuild/optdepends.sh.in  | 28 ++----------
 scripts/libmakepkg/lint_pkgbuild/pkgbase.sh.in     | 19 ++------
 scripts/libmakepkg/lint_pkgbuild/pkgname.sh.in     | 53 +++++++++++++---------
 scripts/libmakepkg/lint_pkgbuild/pkgver.sh.in      | 10 ++--
 scripts/libmakepkg/lint_pkgbuild/provides.sh.in    | 29 +++++-------
 scripts/libmakepkg/util/pkgbuild.sh.in             | 27 +++++++++++
 11 files changed, 178 insertions(+), 172 deletions(-)
 copy scripts/libmakepkg/lint_pkgbuild/{provides.sh.in => checkdepends.sh.in} (50%)
 copy scripts/libmakepkg/lint_pkgbuild/{pkgbase.sh.in => conflicts.sh.in} (50%)
 copy scripts/libmakepkg/lint_pkgbuild/{pkgbase.sh.in => depends.sh.in} (51%)
 copy scripts/libmakepkg/lint_pkgbuild/{provides.sh.in => makedepends.sh.in} (50%)

--
2.16.3

Comments

Allan McRae April 29, 2018, 11:56 a.m. UTC | #1
On 04/04/18 07:48, Eli Schwartz wrote:
> depends, provides, conflicts, replaces, and other variables that are
> meant to contain package names, are now checked to ensure
> 
> 1) the name component contains only characters that would equate to
>    a valid pkgname.
> 2) the version component contains only characters that would equate
>    to a valid pkgver.
> 3) comparison operator is a valid comparison operator (e.g. provides
>    only allows exact = while optdepends doesn't allow anything)
> 
> This also refactors pkgname into a shared utility function, wires up
> pkgbase optdepends and provides to use it, and gives pkgver a touchup
> to allow referencing where it was called from.
> 
> Fixes FS#57833 and a bit of extra.
> 

This looks OK.  Quick testing showed it caught a couple of interesting
cases without a false positive.

Allan
diff mbox

Patch

diff --git a/scripts/Makefile.am b/scripts/Makefile.am
index 7fe169b3..17e54eff 100644
--- a/scripts/Makefile.am
+++ b/scripts/Makefile.am
@@ -69,8 +69,12 @@  LIBMAKEPKG_IN = \
 	libmakepkg/lint_pkgbuild/arch.sh \
 	libmakepkg/lint_pkgbuild/backup.sh \
 	libmakepkg/lint_pkgbuild/changelog.sh \
+	libmakepkg/lint_pkgbuild/checkdepends.sh \
+	libmakepkg/lint_pkgbuild/conflicts.sh \
+	libmakepkg/lint_pkgbuild/depends.sh \
 	libmakepkg/lint_pkgbuild/epoch.sh \
 	libmakepkg/lint_pkgbuild/install.sh \
+	libmakepkg/lint_pkgbuild/makedepends.sh \
 	libmakepkg/lint_pkgbuild/optdepends.sh \
 	libmakepkg/lint_pkgbuild/options.sh \
 	libmakepkg/lint_pkgbuild/package_function.sh \
diff --git a/scripts/libmakepkg/lint_pkgbuild/provides.sh.in b/scripts/libmakepkg/lint_pkgbuild/checkdepends.sh.in
similarity index 50%
copy from scripts/libmakepkg/lint_pkgbuild/provides.sh.in
copy to scripts/libmakepkg/lint_pkgbuild/checkdepends.sh.in
index c2407dc0..5d15bfb2 100644
--- a/scripts/libmakepkg/lint_pkgbuild/provides.sh.in
+++ b/scripts/libmakepkg/lint_pkgbuild/checkdepends.sh.in
@@ -1,6 +1,6 @@ 
 #!/bin/bash
 #
-#   provides.sh - Check the 'provides' array conforms to requirements.
+#   checkdepends.sh - Check the 'checkdepends' array conforms to requirements.
 #
 #   Copyright (c) 2014-2018 Pacman Development Team <pacman-dev@archlinux.org>
 #
@@ -18,45 +18,39 @@ 
 #   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #

-[[ -n "$LIBMAKEPKG_LINT_PKGBUILD_PROVIDES_SH" ]] && return
-LIBMAKEPKG_LINT_PKGBUILD_PROVIDES_SH=1
+[[ -n "$LIBMAKEPKG_LINT_PKGBUILD_CHECKDEPENDS_SH" ]] && return
+LIBMAKEPKG_LINT_PKGBUILD_CHECKDEPENDS_SH=1

 LIBRARY=${LIBRARY:-'@libmakepkgdir@'}

+source "$LIBRARY/lint_pkgbuild/pkgname.sh"
+source "$LIBRARY/lint_pkgbuild/pkgver.sh"
 source "$LIBRARY/util/message.sh"
 source "$LIBRARY/util/pkgbuild.sh"


-lint_pkgbuild_functions+=('lint_provides')
+lint_pkgbuild_functions+=('lint_checkdepends')


-lint_provides() {
-	local a list name provides_list ret=0
+lint_checkdepends() {
+	local checkdepends_list checkdepend name ver ret=0

-	provides_list=("${provides[@]}")
-	for a in "${arch[@]}"; do
-		array_build list "provides_$a"
-		provides_list+=("${list[@]}")
-	done
+	get_pkgbuild_all_split_attributes checkdepends checkdepends_list

-	for name in "${pkgname[@]}"; do
-		if extract_function_variable "package_$name" provides 1 list; then
-			provides_list+=("${list[@]}")
-		fi
+	# save our shell options and turn on extglob
+	local shellopts=$(shopt -p)
+	shopt -s extglob

-		for a in "${arch[@]}"; do
-			if extract_function_variable "package_$name" "provides_$a" 1 list; then
-				provides_list+=("${list[@]}")
-			fi
-		done
-	done
-
-	for provide in "${provides_list[@]}"; do
-		if [[ $provide == *['<>']* ]]; then
-			error "$(gettext "%s array cannot contain comparison (< or >) operators.")" "provides"
-			ret=1
+	for checkdepend in "${checkdepends_list[@]}"; do
+		name=${checkdepend%%@(<|>|=|>=|<=)*}
+		ver=${checkdepend#*@(<|>|=|>=|<=)}
+		lint_one_pkgname checkdepends "$name" || ret=1
+		if [[ $ver != $checkdepend ]]; then
+			check_pkgver "$ver" checkdepends || ret=1
 		fi
 	done

+	eval "$shellopts"
+
 	return $ret
 }
diff --git a/scripts/libmakepkg/lint_pkgbuild/pkgbase.sh.in b/scripts/libmakepkg/lint_pkgbuild/conflicts.sh.in
similarity index 50%
copy from scripts/libmakepkg/lint_pkgbuild/pkgbase.sh.in
copy to scripts/libmakepkg/lint_pkgbuild/conflicts.sh.in
index b2f7af04..d81e9784 100644
--- a/scripts/libmakepkg/lint_pkgbuild/pkgbase.sh.in
+++ b/scripts/libmakepkg/lint_pkgbuild/conflicts.sh.in
@@ -1,6 +1,6 @@ 
 #!/bin/bash
 #
-#   pkgbase.sh - Check the 'pkgbase' variable conforms to requirements.
+#   conflicts.sh - Check the 'conflicts' array conforms to requirements.
 #
 #   Copyright (c) 2014-2018 Pacman Development Team <pacman-dev@archlinux.org>
 #
@@ -18,33 +18,39 @@ 
 #   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #

-[[ -n "$LIBMAKEPKG_LINT_PKGBUILD_PKGBASE_SH" ]] && return
-LIBMAKEPKG_LINT_PKGBUILD_PKGBASE_SH=1
+[[ -n "$LIBMAKEPKG_LINT_PKGBUILD_CONFLICTS_SH" ]] && return
+LIBMAKEPKG_LINT_PKGBUILD_CONFLICTS_SH=1

 LIBRARY=${LIBRARY:-'@libmakepkgdir@'}

+source "$LIBRARY/lint_pkgbuild/pkgname.sh"
+source "$LIBRARY/lint_pkgbuild/pkgver.sh"
 source "$LIBRARY/util/message.sh"
+source "$LIBRARY/util/pkgbuild.sh"


-lint_pkgbuild_functions+=('lint_pkgbase')
+lint_pkgbuild_functions+=('lint_conflicts')


-lint_pkgbase() {
-	local ret=0
+lint_conflicts() {
+	local conflicts_list conflict name ver ret=0

-	if [[ ${pkgbase:0:1} = "-" ]]; then
-		error "$(gettext "%s is not allowed to start with a hyphen.")" "pkgname"
-		return 1
-	fi
-	if [[ ${pkgbase:0:1} = "." ]]; then
-		error "$(gettext "%s is not allowed to start with a dot.")" "pkgbase"
-		ret=1
-	fi
-	if [[ $pkgbase = *[^[:alnum:]+_.@-]* ]]; then
-		error "$(gettext "%s contains invalid characters: '%s'")" \
-				'pkgbase' "${i//[[:alnum:]+_.@-]}"
-		ret=1
-	fi
+	get_pkgbuild_all_split_attributes conflicts conflicts_list
+
+	# save our shell options and turn on extglob
+	local shellopts=$(shopt -p)
+	shopt -s extglob
+
+	for conflict in "${conflicts_list[@]}"; do
+		name=${conflict%%@(<|>|=|>=|<=)*}
+		ver=${conflict#*@(<|>|=|>=|<=)}
+		lint_one_pkgname conflicts "$name" || ret=1
+		if [[ $ver != $conflict ]]; then
+			check_pkgver "$ver" conflicts || ret=1
+		fi
+	done
+
+	eval "$shellopts"

 	return $ret
 }
diff --git a/scripts/libmakepkg/lint_pkgbuild/pkgbase.sh.in b/scripts/libmakepkg/lint_pkgbuild/depends.sh.in
similarity index 51%
copy from scripts/libmakepkg/lint_pkgbuild/pkgbase.sh.in
copy to scripts/libmakepkg/lint_pkgbuild/depends.sh.in
index b2f7af04..f17bc545 100644
--- a/scripts/libmakepkg/lint_pkgbuild/pkgbase.sh.in
+++ b/scripts/libmakepkg/lint_pkgbuild/depends.sh.in
@@ -1,6 +1,6 @@ 
 #!/bin/bash
 #
-#   pkgbase.sh - Check the 'pkgbase' variable conforms to requirements.
+#   depends.sh - Check the 'depends' array conforms to requirements.
 #
 #   Copyright (c) 2014-2018 Pacman Development Team <pacman-dev@archlinux.org>
 #
@@ -18,33 +18,39 @@ 
 #   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #

-[[ -n "$LIBMAKEPKG_LINT_PKGBUILD_PKGBASE_SH" ]] && return
-LIBMAKEPKG_LINT_PKGBUILD_PKGBASE_SH=1
+[[ -n "$LIBMAKEPKG_LINT_PKGBUILD_DEPENDS_SH" ]] && return
+LIBMAKEPKG_LINT_PKGBUILD_DEPENDS_SH=1

 LIBRARY=${LIBRARY:-'@libmakepkgdir@'}

+source "$LIBRARY/lint_pkgbuild/pkgname.sh"
+source "$LIBRARY/lint_pkgbuild/pkgver.sh"
 source "$LIBRARY/util/message.sh"
+source "$LIBRARY/util/pkgbuild.sh"


-lint_pkgbuild_functions+=('lint_pkgbase')
+lint_pkgbuild_functions+=('lint_depends')


-lint_pkgbase() {
-	local ret=0
+lint_depends() {
+	local depends_list depend name ver ret=0

-	if [[ ${pkgbase:0:1} = "-" ]]; then
-		error "$(gettext "%s is not allowed to start with a hyphen.")" "pkgname"
-		return 1
-	fi
-	if [[ ${pkgbase:0:1} = "." ]]; then
-		error "$(gettext "%s is not allowed to start with a dot.")" "pkgbase"
-		ret=1
-	fi
-	if [[ $pkgbase = *[^[:alnum:]+_.@-]* ]]; then
-		error "$(gettext "%s contains invalid characters: '%s'")" \
-				'pkgbase' "${i//[[:alnum:]+_.@-]}"
-		ret=1
-	fi
+	get_pkgbuild_all_split_attributes depends depends_list
+
+	# save our shell options and turn on extglob
+	local shellopts=$(shopt -p)
+	shopt -s extglob
+
+	for depend in "${depends_list[@]}"; do
+		name=${depend%%@(<|>|=|>=|<=)*}
+		ver=${depend#*@(<|>|=|>=|<=)}
+		lint_one_pkgname depends "$name" || ret=1
+		if [[ $ver != $depend ]]; then
+			check_pkgver "$ver" depends || ret=1
+		fi
+	done
+
+	eval "$shellopts"

 	return $ret
 }
diff --git a/scripts/libmakepkg/lint_pkgbuild/provides.sh.in b/scripts/libmakepkg/lint_pkgbuild/makedepends.sh.in
similarity index 50%
copy from scripts/libmakepkg/lint_pkgbuild/provides.sh.in
copy to scripts/libmakepkg/lint_pkgbuild/makedepends.sh.in
index c2407dc0..1d0762fb 100644
--- a/scripts/libmakepkg/lint_pkgbuild/provides.sh.in
+++ b/scripts/libmakepkg/lint_pkgbuild/makedepends.sh.in
@@ -1,6 +1,6 @@ 
 #!/bin/bash
 #
-#   provides.sh - Check the 'provides' array conforms to requirements.
+#   makedepends.sh - Check the 'makedepends' array conforms to requirements.
 #
 #   Copyright (c) 2014-2018 Pacman Development Team <pacman-dev@archlinux.org>
 #
@@ -18,45 +18,39 @@ 
 #   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #

-[[ -n "$LIBMAKEPKG_LINT_PKGBUILD_PROVIDES_SH" ]] && return
-LIBMAKEPKG_LINT_PKGBUILD_PROVIDES_SH=1
+[[ -n "$LIBMAKEPKG_LINT_PKGBUILD_MAKEDEPENDS_SH" ]] && return
+LIBMAKEPKG_LINT_PKGBUILD_MAKEDEPENDS_SH=1

 LIBRARY=${LIBRARY:-'@libmakepkgdir@'}

+source "$LIBRARY/lint_pkgbuild/pkgname.sh"
+source "$LIBRARY/lint_pkgbuild/pkgver.sh"
 source "$LIBRARY/util/message.sh"
 source "$LIBRARY/util/pkgbuild.sh"


-lint_pkgbuild_functions+=('lint_provides')
+lint_pkgbuild_functions+=('lint_makedepends')


-lint_provides() {
-	local a list name provides_list ret=0
+lint_makedepends() {
+	local makedepends_list makedepend name ver ret=0

-	provides_list=("${provides[@]}")
-	for a in "${arch[@]}"; do
-		array_build list "provides_$a"
-		provides_list+=("${list[@]}")
-	done
+	get_pkgbuild_all_split_attributes makedepends makedepends_list

-	for name in "${pkgname[@]}"; do
-		if extract_function_variable "package_$name" provides 1 list; then
-			provides_list+=("${list[@]}")
-		fi
+	# save our shell options and turn on extglob
+	local shellopts=$(shopt -p)
+	shopt -s extglob

-		for a in "${arch[@]}"; do
-			if extract_function_variable "package_$name" "provides_$a" 1 list; then
-				provides_list+=("${list[@]}")
-			fi
-		done
-	done
-
-	for provide in "${provides_list[@]}"; do
-		if [[ $provide == *['<>']* ]]; then
-			error "$(gettext "%s array cannot contain comparison (< or >) operators.")" "provides"
-			ret=1
+	for makedepend in "${makedepends_list[@]}"; do
+		name=${makedepend%%@(<|>|=|>=|<=)*}
+		ver=${makedepend#*@(<|>|=|>=|<=)}
+		lint_one_pkgname makedepends "$name" || ret=1
+		if [[ $ver != $makedepend ]]; then
+			check_pkgver "$ver" makedepends || ret=1
 		fi
 	done

+	eval "$shellopts"
+
 	return $ret
 }
diff --git a/scripts/libmakepkg/lint_pkgbuild/optdepends.sh.in b/scripts/libmakepkg/lint_pkgbuild/optdepends.sh.in
index 7758334c..87e561cb 100644
--- a/scripts/libmakepkg/lint_pkgbuild/optdepends.sh.in
+++ b/scripts/libmakepkg/lint_pkgbuild/optdepends.sh.in
@@ -33,31 +33,13 @@  lint_pkgbuild_functions+=('lint_optdepends')
 lint_optdepends() {
 	local a list name optdepends_list ret=0

-	optdepends_list=("${optdepends[@]}")
-	for a in "${arch[@]}"; do
-		array_build list "optdepends_$a"
-		optdepends_list+=("${list[@]}")
-	done
-
-	for name in "${pkgname[@]}"; do
-		if extract_function_variable "package_$name" optdepends 1 list; then
-			optdepends_list+=("${list[@]}")
-		fi
+	local optdepends_list optdepend name ret=0

-		for a in "${arch[@]}"; do
-			if extract_function_variable "package_$name" "optdepends_$a" 1 list; then
-				optdepends_list+=("${list[@]}")
-			fi
-		done
-	done
+	get_pkgbuild_all_split_attributes optdepends optdepends_list

-	for name in "${optdepends_list[@]}"; do
-		local pkg=${name%%:[[:space:]]*}
-		# the '-' character _must_ be first or last in the character range
-		if [[ $pkg != +([-[:alnum:]><=.+_:]) ]]; then
-			error "$(gettext "Invalid syntax for %s: '%s'")" "optdepend" "$name"
-			ret=1
-		fi
+	for optdepend in "${optdepends_list[@]}"; do
+		name=${optdepend%%:[[:space:]]*}
+		lint_one_pkgname optdepends "$name" || ret=1
 	done

 	return $ret
diff --git a/scripts/libmakepkg/lint_pkgbuild/pkgbase.sh.in b/scripts/libmakepkg/lint_pkgbuild/pkgbase.sh.in
index b2f7af04..b012b226 100644
--- a/scripts/libmakepkg/lint_pkgbuild/pkgbase.sh.in
+++ b/scripts/libmakepkg/lint_pkgbuild/pkgbase.sh.in
@@ -23,6 +23,7 @@  LIBMAKEPKG_LINT_PKGBUILD_PKGBASE_SH=1

 LIBRARY=${LIBRARY:-'@libmakepkgdir@'}

+source "$LIBRARY/lint_pkgbuild/pkgname.sh"
 source "$LIBRARY/util/message.sh"


@@ -30,21 +31,9 @@  lint_pkgbuild_functions+=('lint_pkgbase')


 lint_pkgbase() {
-	local ret=0
-
-	if [[ ${pkgbase:0:1} = "-" ]]; then
-		error "$(gettext "%s is not allowed to start with a hyphen.")" "pkgname"
-		return 1
-	fi
-	if [[ ${pkgbase:0:1} = "." ]]; then
-		error "$(gettext "%s is not allowed to start with a dot.")" "pkgbase"
-		ret=1
-	fi
-	if [[ $pkgbase = *[^[:alnum:]+_.@-]* ]]; then
-		error "$(gettext "%s contains invalid characters: '%s'")" \
-				'pkgbase' "${i//[[:alnum:]+_.@-]}"
-		ret=1
+	if [[ -z $pkgbase ]]; then
+		return 0
 	fi

-	return $ret
+	lint_one_pkgname "pkgbase" "$pkgbase"
 }
diff --git a/scripts/libmakepkg/lint_pkgbuild/pkgname.sh.in b/scripts/libmakepkg/lint_pkgbuild/pkgname.sh.in
index 4024253e..d51c6313 100644
--- a/scripts/libmakepkg/lint_pkgbuild/pkgname.sh.in
+++ b/scripts/libmakepkg/lint_pkgbuild/pkgname.sh.in
@@ -29,34 +29,43 @@  source "$LIBRARY/util/message.sh"
 lint_pkgbuild_functions+=('lint_pkgname')


+lint_one_pkgname() {
+	local type=$1 name=$2 ret=0
+
+
+	if [[ -z $name ]]; then
+		error "$(gettext "%s is not allowed to be empty.")" "$type"
+		ret=1
+		continue
+	fi
+	if [[ ${name:0:1} = "-" ]]; then
+		error "$(gettext "%s is not allowed to start with a hyphen.")" "$type"
+		ret=1
+	fi
+	if [[ ${name:0:1} = "." ]]; then
+		error "$(gettext "%s is not allowed to start with a dot.")" "$type"
+		ret=1
+	fi
+	if [[ $name = *[^[:alnum:]+_.@-]* ]]; then
+		error "$(gettext "%s contains invalid characters: '%s'")" \
+				"$type" "${name//[[:alnum:]+_.@-]}"
+		ret=1
+	fi
+
+	return $ret
+}
+
 lint_pkgname() {
 	local ret=0 i

 	if [[ -z ${pkgname[@]} ]]; then
 		error "$(gettext "%s is not allowed to be empty.")" "pkgname"
-		return 1
+		ret=1
+	else
+		for i in "${pkgname[@]}"; do
+			lint_one_pkgname "pkgname" "$i" || ret=1
+		done
 	fi

-	for i in "${pkgname[@]}"; do
-		if [[ -z $i ]]; then
-			error "$(gettext "%s is not allowed to be empty.")" "pkgname"
-			ret=1
-			continue
-		fi
-		if [[ ${i:0:1} = "-" ]]; then
-			error "$(gettext "%s is not allowed to start with a hyphen.")" "pkgname"
-			ret=1
-		fi
-		if [[ ${i:0:1} = "." ]]; then
-			error "$(gettext "%s is not allowed to start with a dot.")" "pkgname"
-			ret=1
-		fi
-		if [[ $i = *[^[:alnum:]+_.@-]* ]]; then
-			error "$(gettext "%s contains invalid characters: '%s'")" \
-					'pkgname' "${i//[[:alnum:]+_.@-]}"
-			ret=1
-		fi
-	done
-
 	return $ret
 }
diff --git a/scripts/libmakepkg/lint_pkgbuild/pkgver.sh.in b/scripts/libmakepkg/lint_pkgbuild/pkgver.sh.in
index b9e2e439..c105212b 100644
--- a/scripts/libmakepkg/lint_pkgbuild/pkgver.sh.in
+++ b/scripts/libmakepkg/lint_pkgbuild/pkgver.sh.in
@@ -30,13 +30,15 @@  lint_pkgbuild_functions+=('lint_pkgver')


 check_pkgver() {
-	if [[ -z $1 ]]; then
-		error "$(gettext "%s is not allowed to be empty.")" "pkgver"
+	local ver=$1 type=$2
+
+	if [[ -z $ver ]]; then
+		error "$(gettext "%s is not allowed to be empty.")" "pkgver${type:+ in $type}"
 		return 1
 	fi

-	if [[ $1 = *[[:space:]/:-]* ]]; then
-		error "$(gettext "%s is not allowed to contain colons, forward slashes, hyphens or whitespace.")" "pkgver"
+	if [[ $ver = *[[:space:]/:-]* ]]; then
+		error "$(gettext "%s is not allowed to contain colons, forward slashes, hyphens or whitespace.")" "pkgver${type:+ in $type}"
 		return 1
 	fi
 }
diff --git a/scripts/libmakepkg/lint_pkgbuild/provides.sh.in b/scripts/libmakepkg/lint_pkgbuild/provides.sh.in
index c2407dc0..7500a88a 100644
--- a/scripts/libmakepkg/lint_pkgbuild/provides.sh.in
+++ b/scripts/libmakepkg/lint_pkgbuild/provides.sh.in
@@ -23,6 +23,8 @@  LIBMAKEPKG_LINT_PKGBUILD_PROVIDES_SH=1

 LIBRARY=${LIBRARY:-'@libmakepkgdir@'}

+source "$LIBRARY/lint_pkgbuild/pkgname.sh"
+source "$LIBRARY/lint_pkgbuild/pkgver.sh"
 source "$LIBRARY/util/message.sh"
 source "$LIBRARY/util/pkgbuild.sh"

@@ -31,30 +33,21 @@  lint_pkgbuild_functions+=('lint_provides')


 lint_provides() {
-	local a list name provides_list ret=0
+	local provides_list provide name ver ret=0

-	provides_list=("${provides[@]}")
-	for a in "${arch[@]}"; do
-		array_build list "provides_$a"
-		provides_list+=("${list[@]}")
-	done
-
-	for name in "${pkgname[@]}"; do
-		if extract_function_variable "package_$name" provides 1 list; then
-			provides_list+=("${list[@]}")
-		fi
-
-		for a in "${arch[@]}"; do
-			if extract_function_variable "package_$name" "provides_$a" 1 list; then
-				provides_list+=("${list[@]}")
-			fi
-		done
-	done
+	get_pkgbuild_all_split_attributes provides provides_list

 	for provide in "${provides_list[@]}"; do
 		if [[ $provide == *['<>']* ]]; then
 			error "$(gettext "%s array cannot contain comparison (< or >) operators.")" "provides"
 			ret=1
+			continue
+		fi
+		name=${provide%%=*}
+		ver=${provide#*=}
+		lint_one_pkgname provides "$name" || ret=1
+		if [[ $ver != $provide ]]; then
+			check_pkgver "$ver" provides || ret=1
 		fi
 	done

diff --git a/scripts/libmakepkg/util/pkgbuild.sh.in b/scripts/libmakepkg/util/pkgbuild.sh.in
index d35c064b..2db46f1f 100644
--- a/scripts/libmakepkg/util/pkgbuild.sh.in
+++ b/scripts/libmakepkg/util/pkgbuild.sh.in
@@ -116,6 +116,33 @@  get_pkgbuild_attribute() {
 	fi
 }

+get_pkgbuild_all_split_attributes() {
+	local attrname=$1 outputvar=$2 all_list list
+
+	if extract_global_variable "$attrname" 1 list; then
+		all_list+=("${list[@]}")
+	fi
+	for a in "${arch[@]}"; do
+		if extract_global_variable "${attrname}_$a" 1 list; then
+			all_list+=("${list[@]}")
+		fi
+	done
+
+	for name in "${pkgname[@]}"; do
+		if extract_function_variable "package_$name" "$attrname" 1 list; then
+			all_list+=("${list[@]}")
+		fi
+
+		for a in "${arch[@]}"; do
+			if extract_function_variable "package_$name" "${attrname}_$a" 1 list; then
+				all_list+=("${list[@]}")
+			fi
+		done
+	done
+
+	[[ ${all_list[@]} ]] && array_build "$outputvar" all_list
+}
+
 ##
 #  usage : get_full_version()
 # return : full version spec, including epoch (if necessary), pkgver, pkgrel