Skip to content

Fix single quote escaping#1871

Open
kpushkaryov wants to merge 1 commit intojordansissel:mainfrom
kpushkaryov:patch-1
Open

Fix single quote escaping#1871
kpushkaryov wants to merge 1 commit intojordansissel:mainfrom
kpushkaryov:patch-1

Conversation

@kpushkaryov
Copy link

This pull request fixes the cases when file names to be included in RPM package contain single quote but no spaces.

I'm using CentOS 8 with fpm 1.14.1, rpmbuild 4.14.3.

The case of mixed quotes and spaces has been fixed previously in #1774. Unfortunately, escaping by backslash works only if file name contains wildcards, so if I do:

mkdir test
touch test/apostrophe\'s
fpm --verbose -s dir -t rpm -n example test

fpm fails:

Setting workdir {:workdir=>"/tmp", :level=>:info}
Setting from flags: epoch= {:level=>:info}
Setting from flags: iteration= {:level=>:info}
Setting from flags: name=example {:level=>:info}
Setting from flags: url=http://example.com/no-uri-given {:level=>:info}
Setting from flags: version=1.0 {:level=>:info}
Converting dir to rpm {:level=>:info}
Reading template {:path=>"/usr/local/share/gems/gems/fpm-1.14.1/templates/rpm.erb", :level=>:info}
Running rpmbuild {:args=>["rpmbuild", "-bb", "--define", "buildroot /tmp/package-rpm-build-b433757ad1641f2c20bf4bba354406ac73a1a97daa4e6bab5e9dfde1aefa/BUILD", "--define", "_topdir /tmp/package-rpm-build-b433757ad1641f2c20bf4bba354406ac73a1a97daa4e6bab5e9dfde1aefa", "--define", "_sourcedir /tmp/package-rpm-build-b433757ad1641f2c20bf4bba354406ac73a1a97daa4e6bab5e9dfde1aefa", "--define", "_rpmdir /tmp/package-rpm-build-b433757ad1641f2c20bf4bba354406ac73a1a97daa4e6bab5e9dfde1aefa/RPMS", "--define", "_tmppath /tmp", "/tmp/package-rpm-build-b433757ad1641f2c20bf4bba354406ac73a1a97daa4e6bab5e9dfde1aefa/SPECS/example.spec"], :level=>:info}
warning: Macro expanded in comment on line 24: %undefine __check_files {:level=>:info}
 {:level=>:info}
Executing(%prep): /bin/sh -e /tmp/rpm-tmp.wefL3t {:level=>:info}
Executing(%build): /bin/sh -e /tmp/rpm-tmp.K2PXNw {:level=>:info}
Executing(%install): /bin/sh -e /tmp/rpm-tmp.HzY1Bv {:level=>:info}
Processing files: example-1.0-1.x86_64 {:level=>:info}
error: File not found: /tmp/package-rpm-build-b433757ad1641f2c20bf4bba354406ac73a1a97daa4e6bab5e9dfde1aefa/BUILD/test/apostrophe\'s {:level=>:info}
 {:level=>:info}
    Macro expanded in comment on line 24: %undefine __check_files {:level=>:info}
 {:level=>:info}
 {:level=>:info}
RPM build errors: {:level=>:info}
    File not found: /tmp/package-rpm-build-b433757ad1641f2c20bf4bba354406ac73a1a97daa4e6bab5e9dfde1aefa/BUILD/test/apostrophe\'s {:level=>:info}
Process failed: rpmbuild failed (exit code 1). Full command was:["rpmbuild", "-bb", "--define", "buildroot /tmp/package-rpm-build-b433757ad1641f2c20bf4bba354406ac73a1a97daa4e6bab5e9dfde1aefa/BUILD", "--define", "_topdir /tmp/package-rpm-build-b433757ad1641f2c20bf4bba354406ac73a1a97daa4e6bab5e9dfde1aefa", "--define", "_sourcedir /tmp/package-rpm-build-b433757ad1641f2c20bf4bba354406ac73a1a97daa4e6bab5e9dfde1aefa", "--define", "_rpmdir /tmp/package-rpm-build-b433757ad1641f2c20bf4bba354406ac73a1a97daa4e6bab5e9dfde1aefa/RPMS", "--define", "_tmppath /tmp", "/tmp/package-rpm-build-b433757ad1641f2c20bf4bba354406ac73a1a97daa4e6bab5e9dfde1aefa/SPECS/example.spec"] {:level=>:error}

The %files section of the SPEC file is as follows:

%files
%defattr(-,root,root,-)

# Reject config files already listed or parent directories, then prefix files
# with "/", then make sure paths with spaces are quoted. I hate rpm so much.
/test/apostrophe\'s

In the output of strace -s 999 -f -vv fpm --verbose -s dir -t rpm -n example test the following calls are of interest:

lstat("/tmp/package-rpm-build-6f5cd84927d3be59ec8141dcd17db0b18f31141fb01d67a759bb7b28aee6/BUILD/test/apostrophe\\'s", 0x7fff652ea290) = -1 ENOENT (No such file or directory)
write(2, "error: ", 7)      = 7
write(2, "File not found: /tmp/package-rpm-build-6f5cd84927d3be59ec8141dcd17db0b18f31141fb01d67a759bb7b28aee6/BUILD/test/apostrophe\\'s\n", 125 <unfinished ...>

So, the backslash is just passed as is to lstat().

Apparently, rpmbuild checks if the path contains wildcards and treats such paths specially. Other paths are interpreted literally and even backslashes have no effect. Thus, the single quote should be converted to [\']. The backslash is still needed, because otherwise poptParseArgvString() called inside rpmbuild strips the quote away.

The problem wasn't triggered in #1774, because there the paths contained spaces, which are converted to "?" wildcards, thus enabling backslash escaping.

To verify my fix I've performed the following test:

mkdir test2
cd test2
touch apostrophe\'s
touch just\ space
touch perc%\ dollar\$\ ques\?\ ast\*\ lbr\[\ rbr\[\ apos\'
touch apostrophe\'s\ with\ spaces
cd ..
fpm --verbose -s dir -t rpm -n example test2

There was no error and the package looks good:

$ rpm -qlp example-1.0-1.x86_64.rpm 
/test2/apostrophe's
/test2/apostrophe's with spaces
/test2/just space
/test2/perc% dollar$ ques? ast* lbr[ rbr[ apos'

Additionally, I noticed that fpm doesn't escape double quotes and fpm fails with paths containing them, so maybe this needs to be fixed too.

Escaping by backslash works only if file name contains wildcards, so replace single quote with [\']. Just ['] won't work, because it's converted into [] inside rpmbuild.
@jordansissel
Copy link
Owner

Hmm.. Odd. I test this on Fedora 36, rpm v4.17.1, and it seems to work fine on the main branch without this patch?

% find /tmp/z/test2
/tmp/z/test2
/tmp/z/test2/apostrophe's with spaces
/tmp/z/test2/perc% dollar$ ques? ast* lbr[ rbr[ apos'
/tmp/z/test2/just space
/tmp/z/test2/apostrophe's

% bundle exec bin/fpm -f --edit --verbose -s dir -t rpm -n example /tmp/z/test2
...
Created package {:path=>"example-1.0-1.x86_64.rpm"}

The %files section contains:

/tmp/z/test2/apostrophe's
/tmp/z/test2/apostrophe\'s?with?spaces
/tmp/z/test2/just?space
/tmp/z/test2/perc[%]?dollar[$]?ques[?]?ast[*]?lbr[\[]?rbr[\[]?apos\'

The package listing:

% rpm -qlp example-1.0-1.x86_64.rpm 
/tmp/z/test2/apostrophe's
/tmp/z/test2/apostrophe's with spaces
/tmp/z/test2/just space
/tmp/z/test2/perc% dollar$ ques? ast* lbr[ rbr[ apos'

@jordansissel
Copy link
Owner

@kpushkaryov Does this still fail for you? If it does, let me know. I'll try to do some additional testing specifically on CentOS 8

@kpushkaryov
Copy link
Author

Can't reproduce the issue with fpm 1.15.0, rpmbuild 4.14.3 on AlmaLinux 8 (CentOS 8 is not supported anymore). Looks like it has been fixed by this commit to fpm which stopped escaping single quotes in paths without metacharacters.

It's worth noting that rpmbuild's handling of escaping has changed substantially in the meantime. According to docs/manual/spec.md, now you shouldn't escape single quotes. The problem with the backslash on rpmbuild's side is explained in this comment. As of RPM 4.18.0 the changes haven't been released yet.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants