mirror of
https://github.com/bitwarden/browser.git
synced 2025-01-02 18:17:46 +01:00
fix length allowing negative values on Chrome extension (#11926)
This commit is contained in:
parent
19e786f820
commit
888b9e346c
@ -373,7 +373,11 @@ describe("UserStateSubject", () => {
|
|||||||
singleUserId$.next(SomeUser);
|
singleUserId$.next(SomeUser);
|
||||||
await awaitAsync();
|
await awaitAsync();
|
||||||
|
|
||||||
expect(state.nextMock).toHaveBeenCalledWith({ foo: "next" });
|
expect(state.nextMock).toHaveBeenCalledWith({
|
||||||
|
foo: "next",
|
||||||
|
// FIXME: don't leak this detail into the test
|
||||||
|
"$^$ALWAYS_UPDATE_KLUDGE_PROPERTY$^$": 0,
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it("waits to evaluate `UserState.update` until singleUserEncryptor$ emits", async () => {
|
it("waits to evaluate `UserState.update` until singleUserEncryptor$ emits", async () => {
|
||||||
@ -394,7 +398,13 @@ describe("UserStateSubject", () => {
|
|||||||
await awaitAsync();
|
await awaitAsync();
|
||||||
|
|
||||||
const encrypted = { foo: "encrypt(next)" };
|
const encrypted = { foo: "encrypt(next)" };
|
||||||
expect(state.nextMock).toHaveBeenCalledWith({ id: null, secret: encrypted, disclosed: null });
|
expect(state.nextMock).toHaveBeenCalledWith({
|
||||||
|
id: null,
|
||||||
|
secret: encrypted,
|
||||||
|
disclosed: null,
|
||||||
|
// FIXME: don't leak this detail into the test
|
||||||
|
"$^$ALWAYS_UPDATE_KLUDGE_PROPERTY$^$": 0,
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it("applies dynamic constraints", async () => {
|
it("applies dynamic constraints", async () => {
|
||||||
|
@ -43,6 +43,23 @@ import { UserStateSubjectDependencies } from "./user-state-subject-dependencies"
|
|||||||
|
|
||||||
type Constrained<State> = { constraints: Readonly<Constraints<State>>; state: State };
|
type Constrained<State> = { constraints: Readonly<Constraints<State>>; state: State };
|
||||||
|
|
||||||
|
// FIXME: The subject should always repeat the value when it's own `next` method is called.
|
||||||
|
//
|
||||||
|
// Chrome StateService only calls `next` when the underlying values changes. When enforcing,
|
||||||
|
// say, a minimum constraint, any value beneath the minimum becomes the minimum. This prevents
|
||||||
|
// invalid data received in sequence from calling `next` because the state provider doesn't
|
||||||
|
// emit.
|
||||||
|
//
|
||||||
|
// The hack is pretty simple. Insert arbitrary data into the saved data to ensure
|
||||||
|
// that it *always* changes.
|
||||||
|
//
|
||||||
|
// Any real fix will be fairly complex because it needs to recognize *fast* when it
|
||||||
|
// is waiting. Alternatively, the kludge could become a format properly fed by random noise.
|
||||||
|
//
|
||||||
|
// NOTE: this only matters for plaintext objects; encrypted fields change with every
|
||||||
|
// update b/c their IVs change.
|
||||||
|
const ALWAYS_UPDATE_KLUDGE = "$^$ALWAYS_UPDATE_KLUDGE_PROPERTY$^$";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adapt a state provider to an rxjs subject.
|
* Adapt a state provider to an rxjs subject.
|
||||||
*
|
*
|
||||||
@ -420,8 +437,25 @@ export class UserStateSubject<
|
|||||||
private inputSubscription: Unsubscribable;
|
private inputSubscription: Unsubscribable;
|
||||||
private outputSubscription: Unsubscribable;
|
private outputSubscription: Unsubscribable;
|
||||||
|
|
||||||
|
private counter = 0;
|
||||||
|
|
||||||
private onNext(value: unknown) {
|
private onNext(value: unknown) {
|
||||||
this.state.update(() => value).catch((e: any) => this.onError(e));
|
this.state
|
||||||
|
.update(() => {
|
||||||
|
if (typeof value === "object") {
|
||||||
|
// related: ALWAYS_UPDATE_KLUDGE FIXME
|
||||||
|
const counter = this.counter++;
|
||||||
|
if (counter > Number.MAX_SAFE_INTEGER) {
|
||||||
|
this.counter = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
const kludge = value as any;
|
||||||
|
kludge[ALWAYS_UPDATE_KLUDGE] = counter;
|
||||||
|
}
|
||||||
|
|
||||||
|
return value;
|
||||||
|
})
|
||||||
|
.catch((e: any) => this.onError(e));
|
||||||
}
|
}
|
||||||
|
|
||||||
private onError(value: any) {
|
private onError(value: any) {
|
||||||
|
@ -1163,7 +1163,11 @@ describe("CredentialGeneratorService", () => {
|
|||||||
await awaitAsync();
|
await awaitAsync();
|
||||||
const result = await firstValueFrom(stateProvider.getUserState$(SettingsKey, SomeUser));
|
const result = await firstValueFrom(stateProvider.getUserState$(SettingsKey, SomeUser));
|
||||||
|
|
||||||
expect(result).toEqual({ foo: "next value" });
|
expect(result).toEqual({
|
||||||
|
foo: "next value",
|
||||||
|
// FIXME: don't leak this detail into the test
|
||||||
|
"$^$ALWAYS_UPDATE_KLUDGE_PROPERTY$^$": 0,
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it("waits for the user to become available", async () => {
|
it("waits for the user to become available", async () => {
|
||||||
|
Loading…
Reference in New Issue
Block a user