1 From c977424a1d39751fc5055131ad3f7819d421dcc8 Mon Sep 17 00:00:00 2001
2 From: =?UTF-8?q?Ingo=20Kl=C3=B6cker?= <dev@ingo-kloecker.de>
3 Date: Wed, 17 Aug 2022 14:51:19 +0200
4 Subject: [PATCH 1/5] qt: Make sure expiration time is interpreted as unsigned
7 * lang/qt/src/qgpgmeaddexistingsubkeyjob.cpp (add_subkey): Convert
8 expiration time to uint_least32_t.
11 This fixes the corresponding test on 32-bit systems where time_t (the
12 return type of expirationTime()) is a signed 32-bit integer type.
16 lang/qt/src/qgpgmeaddexistingsubkeyjob.cpp | 3 ++-
17 1 file changed, 2 insertions(+), 1 deletion(-)
19 diff --git a/lang/qt/src/qgpgmeaddexistingsubkeyjob.cpp b/lang/qt/src/qgpgmeaddexistingsubkeyjob.cpp
20 index 32e2c292..b74e7a06 100644
21 --- a/lang/qt/src/qgpgmeaddexistingsubkeyjob.cpp
22 +++ b/lang/qt/src/qgpgmeaddexistingsubkeyjob.cpp
23 @@ -64,7 +64,8 @@ static QGpgMEAddExistingSubkeyJob::result_type add_subkey(Context *ctx, const Ke
24 std::unique_ptr<GpgAddExistingSubkeyEditInteractor> interactor{new GpgAddExistingSubkeyEditInteractor{subkey.keyGrip()}};
26 if (!subkey.neverExpires()) {
27 - const auto expiry = QDateTime::fromSecsSinceEpoch(subkey.expirationTime(), Qt::UTC).toString(u"yyyyMMdd'T'hhmmss").toStdString();
28 + const auto expiry = QDateTime::fromSecsSinceEpoch(uint_least32_t(subkey.expirationTime()),
29 + Qt::UTC).toString(u"yyyyMMdd'T'hhmmss").toStdString();
30 interactor->setExpiry(expiry);
37 From 81d4b7f2d7077297d76af5728949d8f2bdff8cd5 Mon Sep 17 00:00:00 2001
38 From: =?UTF-8?q?Ingo=20Kl=C3=B6cker?= <dev@ingo-kloecker.de>
39 Date: Wed, 17 Aug 2022 14:56:13 +0200
40 Subject: [PATCH 2/5] qt,tests: Log the actual error code if the assertion
43 * lang/qt/tests/t-addexistingsubkey.cpp (
44 AddExistingSubkeyJobTest::testAddExistingSubkeyAsync,
45 AddExistingSubkeyJobTest::testAddExistingSubkeySync,
46 AddExistingSubkeyJobTest::testAddExistingSubkeyWithExpiration): Use
47 QCOMPARE instead of QVERIFY for asserting equality.
52 lang/qt/tests/t-addexistingsubkey.cpp | 6 +++---
53 1 file changed, 3 insertions(+), 3 deletions(-)
55 diff --git a/lang/qt/tests/t-addexistingsubkey.cpp b/lang/qt/tests/t-addexistingsubkey.cpp
56 index 589c90bf..2e654cec 100644
57 --- a/lang/qt/tests/t-addexistingsubkey.cpp
58 +++ b/lang/qt/tests/t-addexistingsubkey.cpp
59 @@ -168,7 +168,7 @@ private Q_SLOTS:
60 QSignalSpy spy (this, SIGNAL(asyncDone()));
61 QVERIFY(spy.wait(QSIGNALSPY_TIMEOUT));
63 - QVERIFY(result.code() == GPG_ERR_NO_ERROR);
64 + QCOMPARE(result.code(), static_cast<int>(GPG_ERR_NO_ERROR));
66 QCOMPARE(key.numSubkeys(), 3u);
68 @@ -190,7 +190,7 @@ private Q_SLOTS:
70 const auto result = job->exec(key, sourceSubkey);
72 - QVERIFY(result.code() == GPG_ERR_NO_ERROR);
73 + QCOMPARE(result.code(), static_cast<int>(GPG_ERR_NO_ERROR));
75 QCOMPARE(key.numSubkeys(), 3u);
76 QCOMPARE(key.subkey(2).expirationTime(), 0);
77 @@ -213,7 +213,7 @@ private Q_SLOTS:
79 const auto result = job->exec(key, sourceSubkey);
81 - QVERIFY(result.code() == GPG_ERR_NO_ERROR);
82 + QCOMPARE(result.code(), static_cast<int>(GPG_ERR_NO_ERROR));
84 QCOMPARE(key.numSubkeys(), 3u);
90 From f2b48de26b8f8c48c293423eda712831544924f6 Mon Sep 17 00:00:00 2001
91 From: =?UTF-8?q?Ingo=20Kl=C3=B6cker?= <dev@ingo-kloecker.de>
92 Date: Wed, 17 Aug 2022 15:22:29 +0200
93 Subject: [PATCH 3/5] qt,tests: Make sure expiration time is interpreted as
96 * lang/qt/tests/t-addexistingsubkey.cpp,
97 lang/qt/tests/t-changeexpiryjob.cpp: Convert expiration time to
101 This doesn't change the outcome of the tests (they also pass without
102 this change because of the expiration dates of the test keys), but it's
103 still good practise to treat the expiration time as an unsigned number
104 if the assertions check that the expiration time is in some range.
108 lang/qt/tests/t-addexistingsubkey.cpp | 6 +++---
109 lang/qt/tests/t-changeexpiryjob.cpp | 26 +++++++++++++-------------
110 2 files changed, 16 insertions(+), 16 deletions(-)
112 diff --git a/lang/qt/tests/t-addexistingsubkey.cpp b/lang/qt/tests/t-addexistingsubkey.cpp
113 index 2e654cec..87eadf43 100644
114 --- a/lang/qt/tests/t-addexistingsubkey.cpp
115 +++ b/lang/qt/tests/t-addexistingsubkey.cpp
116 @@ -222,9 +222,9 @@ private Q_SLOTS:
118 const auto allowedDeltaTSeconds = 1;
119 const auto expectedExpirationRange = std::make_pair(
120 - sourceSubkey.expirationTime() - allowedDeltaTSeconds,
121 - sourceSubkey.expirationTime() + allowedDeltaTSeconds);
122 - const auto actualExpiration = key.subkey(2).expirationTime();
123 + uint_least32_t(sourceSubkey.expirationTime()) - allowedDeltaTSeconds,
124 + uint_least32_t(sourceSubkey.expirationTime()) + allowedDeltaTSeconds);
125 + const auto actualExpiration = uint_least32_t(key.subkey(2).expirationTime());
126 QVERIFY2(actualExpiration >= expectedExpirationRange.first,
127 ("actual: " + std::to_string(actualExpiration) +
128 "; expected: " + std::to_string(expectedExpirationRange.first)).c_str());
129 diff --git a/lang/qt/tests/t-changeexpiryjob.cpp b/lang/qt/tests/t-changeexpiryjob.cpp
130 index 090002f3..3da74d46 100644
131 --- a/lang/qt/tests/t-changeexpiryjob.cpp
132 +++ b/lang/qt/tests/t-changeexpiryjob.cpp
133 @@ -70,7 +70,7 @@ private Q_SLOTS:
134 QVERIFY(!key.isNull());
135 QVERIFY(!key.subkey(0).isNull());
136 QVERIFY(!key.subkey(1).isNull());
137 - const auto subkeyExpiration = key.subkey(1).expirationTime();
138 + const auto subkeyExpiration = uint_least32_t(key.subkey(1).expirationTime());
142 @@ -101,7 +101,7 @@ private Q_SLOTS:
143 newExpirationDate.toSecsSinceEpoch() - 10,
144 QDateTime::currentDateTime().addDays(1).toSecsSinceEpoch());
146 - const auto actualExpiration = key.subkey(0).expirationTime();
147 + const auto actualExpiration = uint_least32_t(key.subkey(0).expirationTime());
148 QVERIFY2(actualExpiration >= expectedExpirationRange.first,
149 ("actual: " + std::to_string(actualExpiration) +
150 "; expected: " + std::to_string(expectedExpirationRange.first)).c_str());
151 @@ -110,7 +110,7 @@ private Q_SLOTS:
152 "; expected: " + std::to_string(expectedExpirationRange.second)).c_str());
155 - const auto actualExpiration = key.subkey(1).expirationTime();
156 + const auto actualExpiration = uint_least32_t(key.subkey(1).expirationTime());
157 QCOMPARE(actualExpiration, subkeyExpiration); // unchanged
160 @@ -133,7 +133,7 @@ private Q_SLOTS:
161 QVERIFY(!key.isNull());
162 QVERIFY(!key.subkey(0).isNull());
163 QVERIFY(!key.subkey(1).isNull());
164 - const auto primaryKeyExpiration = key.subkey(0).expirationTime();
165 + const auto primaryKeyExpiration = uint_least32_t(key.subkey(0).expirationTime());
169 @@ -164,11 +164,11 @@ private Q_SLOTS:
170 newExpirationDate.toSecsSinceEpoch() - 10,
171 QDateTime::currentDateTime().addDays(2).toSecsSinceEpoch());
173 - const auto actualExpiration = key.subkey(0).expirationTime();
174 + const auto actualExpiration = uint_least32_t(key.subkey(0).expirationTime());
175 QCOMPARE(actualExpiration, primaryKeyExpiration); // unchanged
178 - const auto actualExpiration = key.subkey(1).expirationTime();
179 + const auto actualExpiration = uint_least32_t(key.subkey(1).expirationTime());
180 QVERIFY2(actualExpiration >= expectedExpirationRange.first,
181 ("actual: " + std::to_string(actualExpiration) +
182 "; expected: " + std::to_string(expectedExpirationRange.first)).c_str());
183 @@ -196,7 +196,7 @@ private Q_SLOTS:
184 QVERIFY(!key.isNull());
185 QVERIFY(!key.subkey(0).isNull());
186 QVERIFY(!key.subkey(1).isNull());
187 - const auto subkeyExpiration = key.subkey(1).expirationTime();
188 + const auto subkeyExpiration = uint_least32_t(key.subkey(1).expirationTime());
192 @@ -228,7 +228,7 @@ private Q_SLOTS:
193 newExpirationDate.toSecsSinceEpoch() - 10,
194 QDateTime::currentDateTime().addDays(3).toSecsSinceEpoch());
196 - const auto actualExpiration = key.subkey(0).expirationTime();
197 + const auto actualExpiration = uint_least32_t(key.subkey(0).expirationTime());
198 QVERIFY2(actualExpiration >= expectedExpirationRange.first,
199 ("actual: " + std::to_string(actualExpiration) +
200 "; expected: " + std::to_string(expectedExpirationRange.first)).c_str());
201 @@ -237,7 +237,7 @@ private Q_SLOTS:
202 "; expected: " + std::to_string(expectedExpirationRange.second)).c_str());
205 - const auto actualExpiration = key.subkey(1).expirationTime();
206 + const auto actualExpiration = uint_least32_t(key.subkey(1).expirationTime());
207 QCOMPARE(actualExpiration, subkeyExpiration); // unchanged
210 @@ -291,7 +291,7 @@ private Q_SLOTS:
211 newExpirationDate.toSecsSinceEpoch() - 10,
212 QDateTime::currentDateTime().addDays(4).toSecsSinceEpoch());
214 - const auto actualExpiration = key.subkey(0).expirationTime();
215 + const auto actualExpiration = uint_least32_t(key.subkey(0).expirationTime());
216 QVERIFY2(actualExpiration >= expectedExpirationRange.first,
217 ("actual: " + std::to_string(actualExpiration) +
218 "; expected: " + std::to_string(expectedExpirationRange.first)).c_str());
219 @@ -300,7 +300,7 @@ private Q_SLOTS:
220 "; expected: " + std::to_string(expectedExpirationRange.second)).c_str());
223 - const auto actualExpiration = key.subkey(1).expirationTime();
224 + const auto actualExpiration = uint_least32_t(key.subkey(1).expirationTime());
225 QVERIFY2(actualExpiration >= expectedExpirationRange.first,
226 ("actual: " + std::to_string(actualExpiration) +
227 "; expected: " + std::to_string(expectedExpirationRange.first)).c_str());
228 @@ -359,7 +359,7 @@ private Q_SLOTS:
229 newExpirationDate.toSecsSinceEpoch() - 10,
230 QDateTime::currentDateTime().addDays(5).toSecsSinceEpoch());
232 - const auto actualExpiration = key.subkey(0).expirationTime();
233 + const auto actualExpiration = uint_least32_t(key.subkey(0).expirationTime());
234 QVERIFY2(actualExpiration >= expectedExpirationRange.first,
235 ("actual: " + std::to_string(actualExpiration) +
236 "; expected: " + std::to_string(expectedExpirationRange.first)).c_str());
237 @@ -368,7 +368,7 @@ private Q_SLOTS:
238 "; expected: " + std::to_string(expectedExpirationRange.second)).c_str());
241 - const auto actualExpiration = key.subkey(1).expirationTime();
242 + const auto actualExpiration = uint_least32_t(key.subkey(1).expirationTime());
243 QVERIFY2(actualExpiration >= expectedExpirationRange.first,
244 ("actual: " + std::to_string(actualExpiration) +
245 "; expected: " + std::to_string(expectedExpirationRange.first)).c_str());
250 From 2fa5c80aeba4528b3bdf41ec5740e7db5d4b6d2b Mon Sep 17 00:00:00 2001
251 From: =?UTF-8?q?Ingo=20Kl=C3=B6cker?= <dev@ingo-kloecker.de>
252 Date: Thu, 18 Aug 2022 10:43:19 +0200
253 Subject: [PATCH 4/5] cpp: Fix handling of "no key" or "invalid time"
256 * lang/cpp/src/gpgaddexistingsubkeyeditinteractor.cpp
257 (GpgAddExistingSubkeyEditInteractor::Private::nextState): Fix inverted
258 logic of string comparisons.
261 This fixes the problem that the interactor didn't return the proper
262 error code if gpg didn't accept the key grip or the expiration date.
266 lang/cpp/src/gpgaddexistingsubkeyeditinteractor.cpp | 4 ++--
267 1 file changed, 2 insertions(+), 2 deletions(-)
269 diff --git a/lang/cpp/src/gpgaddexistingsubkeyeditinteractor.cpp b/lang/cpp/src/gpgaddexistingsubkeyeditinteractor.cpp
270 index 547e613d..8eec7460 100644
271 --- a/lang/cpp/src/gpgaddexistingsubkeyeditinteractor.cpp
272 +++ b/lang/cpp/src/gpgaddexistingsubkeyeditinteractor.cpp
273 @@ -136,7 +136,7 @@ unsigned int GpgAddExistingSubkeyEditInteractor::Private::nextState(unsigned int
274 strcmp(args, "keygen.flags") == 0) {
276 } else if (status == GPGME_STATUS_GET_LINE &&
277 - strcmp(args, "keygen.keygrip")) {
278 + strcmp(args, "keygen.keygrip") == 0) {
282 @@ -157,7 +157,7 @@ unsigned int GpgAddExistingSubkeyEditInteractor::Private::nextState(unsigned int
283 strcmp(args, "keyedit.prompt") == 0) {
285 } else if (status == GPGME_STATUS_GET_LINE &&
286 - strcmp(args, "keygen.valid")) {
287 + strcmp(args, "keygen.valid") == 0) {
288 err = INV_TIME_ERROR;
295 From 2e7a61b898fccc1c20000b79dee83cd980901fa9 Mon Sep 17 00:00:00 2001
296 From: =?UTF-8?q?Ingo=20Kl=C3=B6cker?= <dev@ingo-kloecker.de>
297 Date: Thu, 18 Aug 2022 10:55:09 +0200
298 Subject: [PATCH 5/5] qt,tests: Make test pass on 32-bit systems
300 * lang/qt/tests/t-addexistingsubkey.cpp
301 (AddExistingSubkeyJobTest::testAddExistingSubkeyWithExpiration): Handle
302 negative expiration date.
305 On 32-bit systems the expiration date of the test key overflows. This
306 will cause the AddExistingSubkeyJob to fail. We expect it to fail with
307 an "invalid time" error.
311 lang/qt/tests/t-addexistingsubkey.cpp | 42 +++++++++++++++------------
312 1 file changed, 24 insertions(+), 18 deletions(-)
314 diff --git a/lang/qt/tests/t-addexistingsubkey.cpp b/lang/qt/tests/t-addexistingsubkey.cpp
315 index 87eadf43..c0eee57b 100644
316 --- a/lang/qt/tests/t-addexistingsubkey.cpp
317 +++ b/lang/qt/tests/t-addexistingsubkey.cpp
318 @@ -213,24 +213,30 @@ private Q_SLOTS:
320 const auto result = job->exec(key, sourceSubkey);
322 - QCOMPARE(result.code(), static_cast<int>(GPG_ERR_NO_ERROR));
324 - QCOMPARE(key.numSubkeys(), 3u);
326 - // allow 1 second different expiration because gpg calculates with
327 - // expiration as difference to current time and takes current time
329 - const auto allowedDeltaTSeconds = 1;
330 - const auto expectedExpirationRange = std::make_pair(
331 - uint_least32_t(sourceSubkey.expirationTime()) - allowedDeltaTSeconds,
332 - uint_least32_t(sourceSubkey.expirationTime()) + allowedDeltaTSeconds);
333 - const auto actualExpiration = uint_least32_t(key.subkey(2).expirationTime());
334 - QVERIFY2(actualExpiration >= expectedExpirationRange.first,
335 - ("actual: " + std::to_string(actualExpiration) +
336 - "; expected: " + std::to_string(expectedExpirationRange.first)).c_str());
337 - QVERIFY2(actualExpiration <= expectedExpirationRange.second,
338 - ("actual: " + std::to_string(actualExpiration) +
339 - "; expected: " + std::to_string(expectedExpirationRange.second)).c_str());
340 + if (sourceSubkey.expirationTime() > 0) {
341 + QCOMPARE(result.code(), static_cast<int>(GPG_ERR_NO_ERROR));
343 + QCOMPARE(key.numSubkeys(), 3u);
345 + // allow 1 second different expiration because gpg calculates with
346 + // expiration as difference to current time and takes current time
348 + const auto allowedDeltaTSeconds = 1;
349 + const auto expectedExpirationRange = std::make_pair(
350 + uint_least32_t(sourceSubkey.expirationTime()) - allowedDeltaTSeconds,
351 + uint_least32_t(sourceSubkey.expirationTime()) + allowedDeltaTSeconds);
352 + const auto actualExpiration = uint_least32_t(key.subkey(2).expirationTime());
353 + QVERIFY2(actualExpiration >= expectedExpirationRange.first,
354 + ("actual: " + std::to_string(actualExpiration) +
355 + "; expected: " + std::to_string(expectedExpirationRange.first)).c_str());
356 + QVERIFY2(actualExpiration <= expectedExpirationRange.second,
357 + ("actual: " + std::to_string(actualExpiration) +
358 + "; expected: " + std::to_string(expectedExpirationRange.second)).c_str());
360 + // on 32-bit systems the expiration date of the test key overflows;
361 + // in this case we expect an appropriate error code
362 + QCOMPARE(result.code(), static_cast<int>(GPG_ERR_INV_TIME));