Fix buy not to wipe out concurrent updates
buy() reads the lot, prompts for input, then writes back the lot, triggering a generation oops. Any updates made by other threads while buy() waits for input are wiped out, triggering a seqno mismatch oops. Since commodities are taken from the seller when he puts them on the market, and given to the buyer when the trade executes, the wiped out lot's seller loses his goods without compensation, the other seller gets to keep his goods, and the buyer receives their duplicates. This can be abused by two conspiring countries to duplicate commodities. The seller puts them on the market (say 100 gold bars). The buyer starts a buy command, and waits at its last prompt for the lot to be replaced. The seller takes them off the market (possible, since there's no bid, yet), and sells something else (say one food) quickly enough to get the same lot number assigned. The buyer then completes the buy command. The seller loses one food, the buyer gains 100 gold bars. Replaces a partial fix from v4.0.1, which only caught lots gone away, not lots replaced by new ones.
This commit is contained in:
parent
0563101703
commit
40b11c098c
Notes:
Markus Armbruster
2021-01-17 05:25:14 +01:00
The partial fix was in 4.0.2, actually.
1 changed files with 2 additions and 6 deletions
|
@ -55,7 +55,6 @@ buy(void)
|
|||
struct sctstr sect;
|
||||
struct natstr *natp;
|
||||
struct comstr comm;
|
||||
struct comstr ncomm;
|
||||
struct comstr comt;
|
||||
struct trdstr tmpt;
|
||||
struct ichrstr *ip;
|
||||
|
@ -127,7 +126,7 @@ buy(void)
|
|||
}
|
||||
}
|
||||
canspend = natp->nat_money - tally;
|
||||
getcomm(o, &comm);
|
||||
check_comm_ok(&comm);
|
||||
if (bid * comm.com_amount * buytax > canspend) {
|
||||
pr("You have overextended yourself in the market\n");
|
||||
pr("You can not bid on the current items at that price.\n");
|
||||
|
@ -161,11 +160,8 @@ buy(void)
|
|||
pr("You don't have that much to spend!\n");
|
||||
return RET_FAIL;
|
||||
}
|
||||
getcomm(o, &ncomm);
|
||||
if (!ncomm.com_owner) {
|
||||
pr("That lot has been taken off the market.\n");
|
||||
if (!check_comm_ok(&comm))
|
||||
return RET_FAIL;
|
||||
}
|
||||
if (bid > 0.04 + comm.com_price) {
|
||||
comm.com_price = bid;
|
||||
/* Add five minutes to the time if less than 5 minutes */
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue