10 interesting stories served every morning and every evening.

How we saved 100 terabytes of memory by optimizing 1.1.1.1’s DNS cache

blog.cloudflare.com

Big Pineapple, the plat­form be­hind 1.1.1.1, Gateway DNS, DNS Firewall, AS112, and sev­eral other Cloudflare DNS ser­vices, stores over 250 bil­lion DNS cache en­tries at any given time. At that scale, wast­ing a sin­gle byte per en­try costs more than 250 gi­ga­bytes of mem­ory across our fleet.

Five suc­ces­sive changes to how cache en­tries are stored in mem­ory cut the per-en­try foot­print by over 50%. Across our fleet, these changes freed up roughly 100 ter­abytes of mem­ory, equiv­a­lent to the amount of RAM in 130 of our Gen 13 servers. The cache also got faster. Insert through­put rose 43% and lookup la­tency dropped 19%, as fewer al­lo­ca­tions and bet­ter mem­ory lo­cal­ity meant we did not trade speed for space.

What we cache

On cold start, Big Pineapple starts out with an empty cache. As DNS queries ar­rive, the cache fills un­til it hits its max­i­mum en­try count, at which point we evict older or less pop­u­lar items to make room.

The ex­act cache size varies by data cen­ter. When EDNS Client Subnet (ECS) is in use, au­thor­i­ta­tive servers re­turn dif­fer­ent an­swers de­pend­ing on the clien­t’s net­work, so we cache mul­ti­ple ver­sions of the same query. This in­creases both the num­ber of en­tries and the mem­ory each one con­sumes, mak­ing the op­ti­miza­tions in this post es­pe­cially im­pact­ful for ECS-heavy lo­ca­tions.

Each item in the cache is a key-value pair. The key iden­ti­fies what was queried:

pub struct CacheKey { qname: Name, qtype: Rtype, au­then­ti­cated: bool, tag: Vec<u8>, }

The value stores the DNS re­sponse it­self: the an­swer, au­thor­ity, and ad­di­tional record sec­tions, along with meta­data like the cre­ation time, a hit counter, and the Time-to-Live (TTL).

pub struct CacheEntry { time­stamp: UnixTimeStamp, pub in­cep­tion: Instant, pub ttl: Ttl, pub hits: u32, pub an­swers: Vec<Record>, pub au­thor­ity: Vec<Record>, pub ad­di­tional: Vec<Record>, pub er­rors: Vec<ExtendedError>, … }

Both structs have room for im­prove­ment. Several fields use types that carry over­head we don’t need once the en­try is stored.

Benchmarking mem­ory us­age

To mea­sure the im­pact of each change, we bench­mark by fill­ing the cache with ran­domly gen­er­ated en­tries that roughly match the traf­fic dis­tri­b­u­tion we see in pro­duc­tion: 56% A records, 25% AAAA, and 19% TXT. Each en­try con­tains be­tween one and four records.

TXT records serve as a stand-in for all non-A/​AAAA record types in the bench­mark. Their size is ran­dom­ized be­tween 64 and 224 bytes, close to the av­er­age re­sponse size we see for vari­able-length record types.

We track mem­ory us­age us­ing a cus­tom al­lo­ca­tor that wraps Rust’s System al­lo­ca­tor and records the num­ber and size of al­lo­ca­tions per cache en­try. Alongside mem­ory, we mea­sure in­sert through­put and lookup la­tency across the full cache flow to make sure mem­ory sav­ings don’t come at the cost of per­for­mance.

These in­puts ap­prox­i­mate pro­duc­tion rather than re­pro­duce it ex­actly. Process mem­ory also de­pends on traf­fic mix, cache oc­cu­pancy, al­lo­ca­tor state, and mem­ory used out­side the cache. We there­fore mea­sured res­i­dent mem­ory across pro­duc­tion in­stances dur­ing the roll­out.

The cost of ca­pac­ity

Vec<T> stores three fields: a pointer to heap-al­lo­cated data, the cur­rent length, and the to­tal ca­pac­ity. When you push an item, Vec checks whether the length ex­ceeds the ca­pac­ity and re­al­lo­cates if needed. If there’s room, it just ap­pends the item and in­cre­ments the length.

Once we store a DNS re­sponse in the cache, how­ever, we never mod­ify it again. The ca­pac­ity field serves no pur­pose, but still costs 8 bytes per Vec. The over-al­lo­cated heap space is wasted as well, as a Vec with ca­pac­ity for eight items but only five stored leaves three slots un­used on the heap.

Using Box<[T]> solves both prob­lems. It can’t grow af­ter cre­ation, so it does­n’t need a ca­pac­ity field or re­serve space for fu­ture el­e­ments. The same ap­plies to String, which also car­ries a ca­pac­ity field. Box<str> drops it.

Each cache en­try stores 8 Vec and String fields. Replacing them with Box<[T]> and Box<str> saves 8 bytes per field, 64 bytes per en­try. It also elim­i­nates the ex­cess heap mem­ory that Vec re­serves for fu­ture growth. The com­bined sav­ings add up to over 15 ter­abytes with over 250 bil­lion cache en­tries.

Fewer lists, fewer point­ers

Rather than stor­ing the an­swer, au­thor­ity, and ad­di­tional sec­tions in sep­a­rate lists, we can store a sin­gle list with off­sets to the start of each sec­tion. Since DNS record counts per sec­tion fit in a u16, we can use a u16 (2 bytes) for each off­set, com­pared to the 8-byte pointer and 8-byte length that each sep­a­rate Box<[T]> re­quires.

This re­moves two lists, each with an 8-byte pointer and 8-byte length, and re­places them with two 2-byte off­sets, sav­ing 28 bytes per en­try.

These sav­ings do not al­ways map di­rectly to the num­ber of bytes re­moved from in­di­vid­ual fields. Rust in­serts padding to sat­isfy align­ment re­quire­ments and rounds a struc­t’s size up to a mul­ti­ple of its align­ment. Removing a small field can there­fore elim­i­nate ad­di­tional padding. For ex­am­ple, we also packed sev­eral boolean fields into a sin­gle bit­flag. This re­duced the sur­round­ing padding, caus­ing the struct to shrink by more than the size of the in­di­vid­ual booleans.

Dropping the owner

Each DNS record has an owner, the do­main the record be­longs to. In many cases, this owner is iden­ti­cal to the do­main be­ing queried. For ex­am­ple, a query for ex­am­ple.com A re­turns two records with the same owner:

$ dig ex­am­ple.com A

;; ANSWER SECTION: ex­am­ple.com. 300 IN A 198.51.100.1 ex­am­ple.com. 300 IN A 198.51.100.2

But when a CNAME is in­volved, for ex­am­ple, the record owner can dif­fer from the queried do­main:

$ dig ex­am­ple.com A

;; ANSWER SECTION: ex­am­ple.com. 300 IN CNAME cdn.ex­am­ple.com. cdn.ex­am­ple.com. 300 IN A 198.51.100.1 cdn.ex­am­ple.com. 300 IN A 198.51.100.2

The DNS wire for­mat han­dles re­peated own­ers us­ing name com­pres­sion, as de­fined in RFC 1035. Rather than en­cod­ing the same do­main twice, sub­se­quent oc­cur­rences store a 2-byte pointer to the first oc­cur­rence. A do­main like www.ex­am­ple.com can en­code just www fol­lowed by a pointer to where ex­am­ple.com al­ready ap­peared in the mes­sage.

This works well on the wire, but in our cache we store the full owner name along­side each record. Following com­pres­sion point­ers dur­ing cache lookups is ex­pen­sive on the hot path, so we trade mem­ory for speed.

Most records, how­ever, have an owner iden­ti­cal to the queried do­main. For those, we can drop the owner en­tirely and in­fer it at read time. When the owner dif­fers, such as the A records be­hind a CNAME, we store the full name.

pub struct Record { owner: Option<Box<Name>>, class: Class, ttl: Ttl, rtype: Rtype, data: RecordData, }

When owner is None, re­sponse con­struc­tion re­stores the queried do­main from the cache key, avoid­ing a heap al­lo­ca­tion. This means the record is no longer self-con­tained, but the cache key is al­ready avail­able dur­ing every lookup. When the owner dif­fers, Some stores a pointer to the full name on the heap.

In prac­tice, most cached records have an owner iden­ti­cal to the queried do­main, so the ma­jor­ity re­quire no heap al­lo­ca­tion for the owner field.

Enum siz­ing

Rust enums are sum types: each vari­ant can carry dif­fer­ent data, but the enum is al­ways the size of its largest vari­ant.

pub enum Option<T> { Some(T), None, }

Option is ei­ther Some and holds a value, or None and holds noth­ing. Both vari­ants take the same amount of mem­ory. The enum stores a tag in­di­cat­ing the ac­tive vari­ant, fol­lowed by space large enough for the largest vari­ant’s data. When the vari­ant is None, that space is un­used.

For record data, it seems nat­ural to store each DNS record type as an enum vari­ant:

pub enum RecordData { A(Ipv4Addr), Aaaa(Ipv6Addr), Txt(Txt), Naptr(Naptr), Svcb(Svcb), // … }

But the enum is al­ways as large as its largest vari­ant. In our case, that’s NAPTR at 136 bytes. It stores three vari­able-length text fields, a do­main name, and two in­te­gers. As a re­sult, the full enum, in­clud­ing the vari­ant tag and padding, be­comes 144 bytes.

An A record only needs 4 bytes, and an AAAA record needs 16 bytes. A and AAAA make up over 80% of our traf­fic, so most records waste over 120 bytes on padding. Since a sin­gle cache en­try can store many records this quickly adds up.

Boxing the vari­ants

To solve this prob­lem, we can box the larger vari­ants of the enum, mov­ing them to a sep­a­rate heap al­lo­ca­tion. The enum then stores an 8-byte pointer to the heap, where the data takes up only the size it ac­tu­ally re­quires.

pub enum RecordData { // Small and com­mon vari­ants are stored in­line A(Ipv4Addr), Aaaa(Ipv6Addr), // Large vari­ants are stored on the heap Txt(Box<Txt>), Naptr(Box<Naptr>), Svcb(Box<Svcb>), // … }

For A and AAAA records, this saves 120 bytes per record. Smaller vari­ant types like TXT and CNAME also ben­e­fit. They still oc­cupy the 24-byte enum, but their heap al­lo­ca­tion is sized to their ac­tual data rather than padded to 144 bytes. NAPTR, the largest vari­ant, ac­tu­ally pays slightly more. It now adds the cost of a heap pointer and al­lo­ca­tion over­head. But NAPTR records are rare in prac­tice, so the trade­off is worth it.

But box­ing the larger record vari­ants in­tro­duces costs of its own.

The costs of box­ing

Boxing has two costs. The first is al­lo­ca­tor over­head. Each boxed vari­ant be­comes a sep­a­rate heap al­lo­ca­tion, and al­lo­ca­tors round up to the near­est size class. Big Pineapple uses je­mal­loc, an al­lo­ca­tor de­signed for mul­ti­threaded, al­lo­ca­tion-heavy work­loads. je­mal­loc groups al­lo­ca­tions of sim­i­lar sizes into fixed-size bins. A TXT record re­quests 32 bytes and fits ex­actly into a 32-byte bin, wast­ing noth­ing, but an MX record re­quests 40 bytes and rounds up to 48, wast­ing 8 bytes.

The sec­ond cost is poor mem­ory lo­cal­ity. Without box­ing, the record enum val­ues for a cache en­try sit in a sin­gle con­tigu­ous al­lo­ca­tion. With box­ing, data for each boxed vari­ant lives in a sep­a­rate heap re­gion. Reading it re­quires fol­low­ing a pointer, and when that pointer lands far from the rest of the en­try, the CPU has to fetch a new cache line. With mil­lions of cache en­tries, boxed data ends up scat­tered across the heap rather than packed to­gether.

Neither cost is cat­a­strophic on its own, but elim­i­nat­ing both, as the next sec­tion shows, yields a mea­sur­able im­prove­ment in both mem­ory us­age and lookup la­tency.

Storing records in wire for­mat

An ob­vi­ous next step would be to store the full DNS re­sponse in wire for­mat, patch­ing only per-client fields like the mes­sage ID on each lookup. But this has draw­backs. DNSSEC records are only in­cluded when the client sets the DO (DNSSEC OK) flag. Storing a com­plete wire for­mat mes­sage means ei­ther caching two vari­ants, one with DNSSEC and one with­out, or fil­ter­ing them out of an al­ready-built mes­sage. There is also a cost to pars­ing the full mes­sage on every lookup, which the enum ap­proach we just de­scribed avoids by stor­ing al­ready-parsed records.

As a mid­dle ground, we store just the record data as raw bytes, while keep­ing the rest of the cache en­try as struc­tured fields. Instead of a list of parsed enum vari­ants, we store the records as a sin­gle Box<[u8]> con­tain­ing each record en­coded as a 2-byte length pre­fix fol­lowed by its raw bytes.

This elim­i­nates the per-vari­ant enum over­head and the boxed heap al­lo­ca­tions from the pre­vi­ous op­ti­miza­tion. The data also be­comes packed con­tigu­ously, which im­proves CPU cache lo­cal­ity. The trade­off is that records can no longer be ran­domly in­dexed. We have to it­er­ate through the buffer se­quen­tially. This adds some com­plex­ity for fea­tures like round-robin ro­ta­tion of A/AAAA records, but since record counts per en­try are small, the cost is neg­li­gi­ble.

When build­ing a DNS re­sponse from cached records, most record types can be copied di­rectly from the buffer into the out­go­ing mes­sage. Previously, each parsed record had to be se­ri­al­ized field by field back into DNS wire for­mat. The new lay­out skips that work for A, AAAA, TXT, and all DNSSEC record types by copy­ing their en­coded bytes di­rectly. Only records con­tain­ing do­main names, such as CNAME, NS, MX, and SOA, still re­quire pars­ing so we can ap­ply DNS name com­pres­sion. Since records that sup­port di­rect copy­ing make up the vast ma­jor­ity of our traf­fic, this change re­duces work on the lookup path. Combined with im­proved mem­ory lo­cal­ity, this re­duced cache lookup la­tency by 5% in our bench­marks.

To build the record data buffer, we write into a reusable scratch­space buffer that per­sists across cache in­ser­tions. Since pre­vi­ous writes have al­ready grown it, the buffer rarely needs to be re­al­lo­cated. Records vary in size, so we do not know the ex­act buffer size un­til they have been se­ri­al­ized. Once the records are in the scratch­space buffer, we al­lo­cate a Box<[u8]> and mem­cpy the data into it. This re­places the sep­a­rate al­lo­ca­tion for each boxed record with one al­lo­ca­tion for all record data. It also avoids the waste from shrink­ing a Vec<u8>, where the al­lo­ca­tor may not be able to re­claim the un­used tail of the orig­i­nal al­lo­ca­tion. In our bench­mark, this change alone in­creased cache in­sert through­put by 13%.

The re­sults

The pro­duc­tion mea­sure­ments show how the bench­marked per-en­try sav­ings trans­lated to whole-process res­i­dent mem­ory. The graph be­low shows p90, p98, and p99 mem­ory us­age across Big Pineapple in­stances. The first dashed line marks the start of the roll­out on May 18, 2026, and the sec­ond marks its com­ple­tion across all ser­vices on July 6, 2026. Each re­lease in­tro­duced one or more of the op­ti­miza­tions de­scribed above, so mem­ory us­age dropped in steps rather than all at once.

As each re­lease rolled out, restarted in­stances be­gan with empty caches and con­sumed more mem­ory as those caches filled. The sta­ble plateaus there­fore rep­re­sent steady-state mem­ory us­age bet­ter than the ini­tial dips.

Per-instance mem­ory us­age dropped across all per­centiles. At p99, mem­ory dropped from 9.3 GB to 5.3 GB, a 43% re­duc­tion in res­i­dent mem­ory. At p90, mem­ory dropped from 6.5 GB to 3.8 GB, a 42% re­duc­tion. Instances with fuller caches saw the largest ab­solute sav­ings.

In our bench­marks, these five op­ti­miza­tions re­duced the per-en­try mem­ory foot­print from 953 bytes to 420 bytes, a 56% re­duc­tion. Per-entry al­lo­ca­tions dropped from 1.1 KB to 461 bytes. The re­duc­tions mea­sured in pro­duc­tion are smaller be­cause res­i­dent mem­ory in­cludes the cache along­side all other process data. After the roll­outs set­tled, ag­gre­gate work­ing-set mem­ory across the fleet was roughly 100 ter­abytes lower.

Performance also im­proved. Cache in­sert through­put in­creased by 43%, while lookup la­tency dropped by 19%.

Metric

Before

After

Change

Per-entry net foot­print

953 bytes

420 bytes

-56%

Per-entry al­lo­ca­tions

1.1 KB

461 bytes

-58%

Cache in­sert through­put

625,000 en­tries/​s

893,000 en­tries/​s

+43%

Cache lookup la­tency

828 ns

670 ns

-19%

We plan to rein­vest the freed mem­ory into in­creas­ing cache ca­pac­ity with­out in­creas­ing our mem­ory us­age, which im­proves cache hit rates and re­duces up­stream query vol­ume. We’re also ex­plor­ing fur­ther op­ti­miza­tions to the cache it­self.

To learn more about Big Pineapple, see How Rust and Wasm power Cloudflare’s 1.1.1.1. If you work on DNS or other large sys­tems, share the op­ti­miza­tions that have worked for you in the Cloudflare Community or on the Cloudflare Developers Discord.

"iT woRKs BeTter in THe aPp!!"

shkspr.mobi

The mon­key-punch­ers at Google never quite seem to fin­ish any of their apps. There’s al­ways some use­ful bit of work left un­done, or show­stop­ping bug which re­mains un­fixed, a thou­sand jagged edges as yet un­solved by the great­est minds of their gen­er­a­tion.

I wanted to sub­scribe to an events cal­en­dar. I had a URl. I had my Google™ Pixel® phone run­ning the lat­est Android© 17 with an up­dated cal­en­dar app. Is it pos­si­ble to click on a cal­en­dar link and add it to my phone?

No.

Here’s what Google has to say about the mat­ter:

Really?!? I mean, fuck­ing re­ally????

This is­n’t the most com­plex soft­ware en­gi­neer­ing task known to hu­man­ity. Add a + but­ton. Pop open a text en­try field. Validate. Save. Done. I’m sure even the shitty Gemini model can vibe code that in a cou­ple of months, right?

Anyway, I opened cal­en­dar.google.com on my phone (using desk­top mode), added the cal­en­dar, and it mag­i­cally ap­peared in the app.

This is just pa­thetic.

In fair­ness, this is­n’t only a Google prob­lem. Many com­pa­nies want a per­ma­nent pres­ence on your home­screen and think you’re too thick to use your browser’s book­marks fea­ture. Maybe they’re right. Maybe an app is the only way to in­crease the en­gage­ment KPI suf­fi­ciently so Quinn in the lead­er­ship squad can hit their OKRs and get a bonus.

So they build an app. Or, rather, they half-arse it. I’ve lost count of the num­ber of times I’ve been told it’s eas­ier if you use our app” only to be un­cer­e­mo­ni­ously punted back to the web when I try to do any­thing out­side of the ap­p’s nar­row stric­tures.

I was there in the early days of phone apps. I built stuff for Symbian, BlackBerry, even the bloody Palm Pilot! The cen­tral prob­lem with apps has al­ways been that they are hard to up­date. Every new bit of func­tion­al­ity - or even a new page - needs to be tested on a thou­sand de­vices. Once done, it takes an age to dis­trib­ute to users. The only way to solve that is to have the app dy­nam­i­cally pull in new func­tion­al­ity from a re­mote re­source.

At which point, you’ve rein­vented the Web browser!

Sure, there are some things you can only do with an app (although browsers are catch­ing up), and hav­ing an icon on the home­screen is use­ful (which is easy for sites to add), as is of­fline func­tion­al­ity (which, again, is pos­si­ble on the web).

Oh.

If you want an app, fine. Do it. Just fin­ish the job please!

Intelligent transcription with Gemini 3.5 Transcribe

blog.google

Aug 26, 2026

|

Our lat­est speech-to-text model de­signed for pre­cise and in­tel­li­gent real-time tran­scrip­tion.

Diego Melendo Casado

Senior Director, Engineering, Gemini Audio

Luke Leonhard

Chief of Staff, Gemini Audio, on be­half of Gemini Audio Team

Your browser does not sup­port the au­dio el­e­ment.

Listen to ar­ti­cle

[[duration]] min­utes

This con­tent is gen­er­ated by Google AI. Generative AI is ex­per­i­men­tal

Today, we’re in­tro­duc­ing Gemini 3.5 Transcribe, our most pre­cise speech-to-text model yet, de­signed for in­tel­li­gent voice in­ter­ac­tions. Unlike con­ven­tional speech recog­ni­tion mod­els that strug­gle with back­ground noise, com­plex jar­gon, and dis­flu­ency cleanup, Gemini 3.5 Transcribe con­verts raw au­dio di­rectly into ac­cu­rate, pol­ished, for­mat­ted text.

Across our prod­ucts like the Gemini app and on Android, we’ve seen con­sumers al­ready ben­e­fit­ing from this tran­scrip­tion model with new voice ca­pa­bil­i­ties like Rambler on Android and in the Gemini app on ma­cOS. Now, de­vel­op­ers can build sim­i­lar ca­pa­bil­i­ties with Gemini 3.5 Transcribe in the Gemini API in Google AI Studio and Gemini Enterprise Agent Platform.

We’ve built 3.5 Transcribe to plug seam­lessly into your de­vel­oper work­flows, whether you’re build­ing voice agents, real-time cap­tion­ing tools, or post-call an­a­lyt­ics pipelines. The model is avail­able across two sep­a­rate APIs:

Real-time stream­ing: Delivers con­tin­u­ous, bidi­rec­tional stream­ing with sub-sec­ond la­tency for in­ter­ac­tive voice apps via the Live API us­ing gem­ini-3.5-tran­scribe-live.

Pre-recorded au­dio pro­cess­ing: Transcribes recorded au­dio, meet­ings, call logs, and more with speaker at­tri­bu­tion and word-level time­stamps via the Interactions API us­ing gem­ini-3.5-tran­scribe.

Get more pre­cise and in­tel­li­gent tran­scrip­tion

Gemini 3.5 Transcribe is de­signed to cap­ture your nat­ural speak­ing style to bet­ter un­der­stand your in­tent and rec­og­nize cus­tom vo­cab­u­lary, so you can ex­e­cute tasks with your voice.

Smart tran­scrip­tion: Seamlessly han­dles self-cor­rec­tions (like let’s meet Tuesday—no, Wednesday”), re­moves filler words (“ums” and “ahs”), auto-for­mats your text.

Function call­ing: The model can del­e­gate com­plex tasks (such as im­age gen­er­a­tion and file analy­sis) to other Gemini mod­els via func­tion calls. Currently avail­able in the Gemini ma­cOS app.

More pre­cise tran­scrip­tion: As mea­sured by Artificial Analysis, achieves an av­er­age Word Error Rate (WER) of 4.0% for stream­ing and 2.6% for non-stream­ing use-cases. It shows strong per­for­mance across noisy, real-world en­vi­ron­ments, ac­cu­rately cap­tur­ing al­phanu­meric en­ti­ties like postal codes and or­der IDs.

Custom vo­cab­u­lary: Recognizes spe­cial­ized jar­gon and unique spellings by seam­lessly adapt­ing tran­scrip­tions to your pro­vided cus­tom vo­cab­u­lary.

Global lan­guage sup­port: Automatically de­tects and tran­scribes over 85 lan­guages, seam­lessly han­dling re­gional ac­cents and di­verse di­alects.

Multi-speaker iden­ti­fi­ca­tion: Accurately at­trib­utes speech in pre-recorded au­dio with time­stamps for up to three speak­ers (support for 3+ speak­ers is ex­per­i­men­tal).

Gemini 3.5 Transcribe’s per­for­mance rep­re­sents a ma­jor ad­vance­ment from our pre­vi­ous tran­scrip­tion model, Chirp 3, of­fer­ing new ca­pa­bil­i­ties, im­proved word er­ror rates, and sig­nif­i­cantly bet­ter la­tency. As mea­sured by Artificial Analysis, time to fi­nal tran­scrip­tion, for ex­am­ple, im­proves by 70%. On the FLEURS bench­mark across a set of top lan­guages and lo­cales, the model de­liv­ers pre­cise mul­ti­lin­gual per­for­mance, im­prov­ing over Chirp 3, and achiev­ing a 5.50% WER in stream­ing mode and 5.04% WER in non-stream­ing use-cases.

Experience smart tran­scrip­tion and ad­vanced dic­ta­tion

In ad­di­tion to the Gemini API in the Google AI Studio and Gemini Enterprise Agent Platform, 3.5 Transcribe goes fur­ther than stan­dard speech-to-text to make work­ing across Google feel more nat­ural and in­tu­itive. By bring­ing con­text-aware un­der­stand­ing di­rectly into every­day sur­faces like Gboard, Antigravity, the Gemini app, and Chrome, it cap­tures nu­ances, in­tent, and in­line ed­its with ease.

On Gboard on Android, through the new Rambler fea­ture, 3.5 Transcribe trans­forms spo­ken thoughts into well-for­mat­ted text, fil­ter­ing out filler words. You can also use your voice to make ed­its, cor­rect mis­spellings, and change the writ­ing style.

On Google Antigravity, 3.5 Transcribe pairs screen con­text and chat his­tory, with your per­mis­sion, to en­sure pin­point tran­scrip­tion ac­cu­racy across file names, agent thoughts, and ac­tive doc­u­ments.

In Google AI Studio, you can ac­cess 3.5 Transcribe in Build mode to vibe code apps with your voice on the fly.

In the Gemini app on ma­cOS, 3.5 Transcribe not only tran­scribes your free nat­ural speech into clean for­mat­ted text, but also en­ables voice com­mands that can pair seam­lessly with screen con­text to power com­plex work­flows. By call­ing on other Gemini mod­els in the back­ground to han­dle the heavy lift­ing, the model makes it ef­fort­less to sum­ma­rize lo­cal files, re­pur­pose text across apps, or gen­er­ate im­ages right at your cur­sor—us­ing just your voice.

Coming soon to Chrome, you’ll be able to talk to type in any web field — mak­ing it ef­fort­less to dic­tate replies, draft posts, or prompt Gemini in Chrome more nat­u­rally and eas­ily with your voice.

Read the early re­views

By lever­ag­ing the Gemini Live API, de­vel­oper plat­forms such as Agora, Fishjam, LangChain, LiveKit, Pipecat, Vercel, and Vision Agents en­able de­vel­op­ers to build and de­ploy high-per­for­mance voice-dri­ven in­ter­faces with ease. These plat­forms man­age com­plex real-time me­dia stream­ing in­fra­struc­ture be­hind the scenes, al­low­ing de­vel­op­ers to fo­cus en­tirely on craft­ing the user ex­pe­ri­ence.

Companies like vivo, Intellitek Health, and Lingopal have also shared pos­i­tive feed­back on 3.5 Transcribe, high­light­ing its im­pres­sive la­tency, ac­cu­racy, and ex­pan­sive lan­guage sup­port.

Start us­ing 3.5 Transcribe to­day

For de­vel­op­ers: In pub­lic pre­view in the Gemini API via Google AI Studio and Google Antigravity.

For en­ter­prises: In pub­lic pre­view via Gemini Enterprise Agent Platform and com­ing soon to Gemini Enterprise for Customer Experience.

For every­one: In Gemini app on ma­cOS in English, Rambler on Android in se­lect coun­tries and lan­guages, and com­ing soon to Chrome.

Get the lat­est news from Google in your in­box

Sign up for our newslet­ters with prod­uct up­dates, event in­for­ma­tion, spe­cial of­fers, and more.

Your in­for­ma­tion will be used in ac­cor­dance with Google’s pri­vacy pol­icy. You may opt out at any time.

Access Denied

www.gatesnotes.com

Reference #18.6c24c317.1787899885.37c03da

https://​er­rors.edge­suite.net/​18.6c24c317.1787899885.37c03da

Refund4Freedom

en.refund4freedom.org

Refund4Freedom / Demands / Refund / Supporting Material / Share!

Get your Windows li­cense re­fund now!

We all know the joy of ac­quir­ing a new lap­top and the ex­cite­ment of ex­plor­ing its fea­tures and func­tion­al­i­ties. However, the vast ma­jor­ity of lap­tops are only sold with a spe­cific pro­pri­etary op­er­at­ing sys­tem: Microsoft Windows. The ven­dors do not re­move the Windows li­cense, and you must pay the en­tire price, even if you do not want to use this sys­tem.

This is un­fair and we want to change it! Con­sumers should be able to buy lap­tops with­out any spe­cific op­er­at­ing sys­tem, and should not have to pay the li­cense price if they don’t want to.

Request your re­fund now!

Demands

You should not have to pay for soft­ware you don’t want. Devices like lap­tops and smart­phones are gen­eral pur­pose com­put­ers so, they should be neu­tral in re­la­tion to the soft­ware they run. Manufacturers and ven­dors should not have the right to im­pose spe­cific op­er­at­ing sys­tems on you. When you re­quest a re­fund, the process should be easy, quick and straight­for­ward. Here’s what we de­mand:

Do not re­strict users to spe­cific soft­ware. Device man­u­fac­tur­ers and ven­dors should not im­pose an op­er­at­ing sys­tem or soft­ware on con­sumers, and should not force them to pay for soft­ware that they don’t want. Laptops and smart­phones are gen­eral pur­pose com­put­ers, so con­sumers should be able to run the soft­ware they want on their de­vices.

Transparent pric­ing. Consumers should have the right to de­cline pre-in­stalled soft­ware, in­clud­ing the op­er­at­ing sys­tem, but still be able to buy the lap­top with­out it.

Hassle-free re­funds. Manufacturers and ven­dors should clearly pub­lish the steps for re­quest­ing and ob­tain­ing a re­fund on their web­sites. The process should be sim­ple, easy and ac­ces­si­ble to any con­sumer. No one should go through un­nec­es­sary or com­pli­cated pro­ce­dures i.e. send­ing the en­tire com­puter to a ser­vice cen­tre just to re­move un­wanted soft­ware.

Take ac­tion!

How to re­quest your li­cense re­fund

1

Start up the PC and take pic­tures

Take pic­tures of the screen of the clauses of the con­tract where the re­im­burse­ment is in­di­cated or make a video by scrolling through the whole con­tract (maybe use­ful later). If pos­si­ble, do not for­mat/​erase yet your com­puter stor­age.

2

Contact the man­u­fac­tur­er’s cus­tomer ser­vice

Contact the man­u­fac­turer by tele­phone or, bet­ter still, chat/​email, and keep the rel­e­vant cor­re­spon­dence. For the tele­phone, note the date, time and with whom you spoke. For chat, copy/​paste what was writ­ten.

3

If they re­spond neg­a­tively…

Problem Not Solved: fill-in the Refund Form and send it to the man­u­fac­turer.

4

Supporting Material

Here you can find use­ful ma­te­r­ial to re­fund the cost of the Windows op­er­at­ing sys­tem.

Manufacturers

Not all man­u­fac­tur­ers and ven­dors are equal. Some re­act dif­fer­ently and treat con­sumers bet­ter. We have a lot of ex­pe­ri­ence in re­quest­ing re­funds, and keep track of those who re­spect your right to choose—and those who don’t. Below we pro­vide re­ports on man­u­fac­tur­ers con­cern­ing their li­censes and re­fund poli­cies to help you in get­ting your money back.

HP

HP does not have a re­im­burse­ment pro­ce­dure for Windows.

Several con­tact at­tempts were made by dif­fer­ent cus­tomers, and were al­ways ig­nored by HP.

Lenovo

Lenovo has a re­im­burse­ment pro­ce­dure for Windows.Lenovo li­cense re­im­burse­ment pro­ce­dure for Windows.

The PC must be shipped to a Lenovo as­sis­tance cen­tre.

Asus

Asus has a re­im­burse­ment pro­ce­dure for Windows.

No need to ship the PC to Asus.

Asus’s re­im­burse­ment pro­ce­dure is not pub­lished on their web­site.

Asus gives a re­im­burse­ment be­tween 9 and 65 eu­ros, de­pend­ing on the Windows ver­sion.

Send an e-mail to info@asus.it in­di­cat­ing the PC se­r­ial num­ber and your bank de­tails, within 30 days of pur­chase and with­out ac­cept­ing the EULA when you first turn on the ma­chine.

Dell

Dell does not have a re­im­burse­ment pro­ce­dure for Windows.

Dell’s terms and con­di­tions, in Article 7.3, ex­plic­itly states that in the event of non-ap­proval of the op­er­at­ing sys­tem li­cence, the com­puter must be re­turned.

Acer

Acer has a re­im­burse­ment pro­ce­dure for Windows. Acer li­cense re­im­burse­ment pro­ce­dure for Windows.

The PC must be shipped to an Acer as­sis­tance cen­tre.

Forms to be filled in and sub­mit­ted can be found on the Acer web­site.

Reports

Reports re­ceived. Get in­spired. Explore in­for­ma­tion from other users like you who got their li­cense fee back!

IT for s.r.l.

Acer

Following re­peated un­suc­cess­ful tele­phone con­tacts, the ITfor com­pany in Turin took Acer Italia to the Justice of the Peace con­test­ing the man­ner in which the li­cense was re­im­bursed. After sev­eral hear­ings and ad­journ­ments, Acer Italia granted pay­ment of 50 eu­ros + 100 eu­ros for le­gal fees in­curred. Writ of Lawsuit, Minutes of Conciliation, Complete doc­u­men­ta­tion

Luca Bonissi

Mediacom

After pur­chas­ing a Mediacom PC, Luca went di­rectly to Datamatic S.p.A. (the par­ent com­pany of the Mediacom brand) to re­quest a re­fund of the Windows li­cense. Only af­ter the le­gal sum­mons was served, and just be­fore the le­gal hear­ing, Luca re­ceived an of­fer for a pri­vate trans­ac­tion and awarded a re­fund of 44 eu­ros. Complete doc­u­men­ta­tion

Luca Bonissi

Microsoft

Luca, af­ter some per­se­ver­ance, reached the Microsoft Technical Support of Microsoft S.r.l. (representing Microsoft in Italy), which ac­tu­ally pro­vides a pro­ce­dure for re­fund­ing the Windows li­cense on prod­ucts sold by the com­pany (in this case, a Microsoft Surface). After sev­eral emails and com­mu­ni­ca­tions, Luca re­ceived a re­fund of 43 eu­ros. Complete doc­u­men­ta­tion

Luca Bonissi

Lenovo

Following a lengthy le­gal dis­pute, the judg­ment in the sec­ond in­stance awarded a re­fund of 42 eu­ros for the Windows li­cense, 1,000 for le­gal fees, and or­dered Lenovo Italy S.r.l to re­im­burse 20,000 eu­ros in dam­ages for ag­gra­vated lit­i­ga­tion li­a­bil­ity. Complete doc­u­men­ta­tion

Luca Bonissi

HP

The re­im­burse­ment re­quest was de­nied sev­eral times, but the Justice of the Peace in Monza awarded a 61 euro re­im­burse­ment for pre-in­stalled li­censes (of both Windows 10 Home and Office 365 Personal). Complete doc­u­men­ta­tion

Francesca Tregnaghi

Dell

After a cou­ple of Italian le­gal emails (PEC emails), the 51 euro re­fund for the Windows 10 Home Edition li­cense was granted. Complete doc­u­men­ta­tion

Vincenzo Castiglia

Lenovo

After a long se­ries of emails and phone calls, the 42 euro re­fund for the Windows 10 Home Edition li­cense was granted. For the pay­ment, Vincenzo chose to give Italian Linux Society’s bank de­tails. Complete doc­u­men­ta­tion

Silvia

Lenovo

After a par­tic­u­larly pro­longed email ex­change, a re­fund of 47 eu­ros for the Windows 10 Home Edition li­cense was granted. Complete doc­u­men­ta­tion

Luca Bonissi

Lenovo

Oggetto del con­tendere è stato - come in di­versi al­tri casi - la pre­sunta ne­ces­sità di resti­tuire il PC. Alla fine è stato ri­conosci­uto un rim­borso di 75 euro per la li­cenza Windows 11 Home. Complete doc­u­men­ta­tion

Luca Bonissi

Acer

Although Acer has a pro­ce­dure for re­fund­ing the Windows li­cense, it in­volves send­ing the PC, long wait­ing times and de­risory com­pen­sa­tion, so the pro­ce­dure is in­con­ve­nient and im­prac­ti­cal. The lengthy ex­change of le­gal Italian emails (PEC emails) be­tween Luca and Acer, cul­mi­nat­ing in the sug­ges­tion of a court case, ended in a 129 euro re­fund. Complete doc­u­men­ta­tion

Giuseppe Salustri

MSI

After many dif­fi­cul­ties raised by MSI, in­clud­ing ship­ping the com­puter to the ser­vice cen­ter in Poland, long wait­ing times, and re­minders, Giuseppe fi­nally got a re­fund of 40 eu­ros (net of ship­ping costs, ab­surdly charged to the cus­tomer). It is rec­om­mended not to write to the email ad­dress for sup­port, but to reg­is­ter on the MSI site and open a ticket spec­i­fy­ing the se­r­ial num­ber, first name, last name, mail­ing ad­dress, and phone num­ber right away.

Get a li­cence free de­vice

Want to buy a li­cence-free PC di­rectly? Search for your near­est Linux-friendly shop on LinuxSi! (Italian-only).

My de­vice is a smart­phone. Check how you can in­stall a dif­fer­ent op­er­at­ing sys­tem on your smart­phone FSFEs Free Your Android site.

Share the cam­paign

The more peo­ple know, the stronger we are! Share this cam­paign with your friends, fam­ily, and on your so­cial net­works, by us­ing #Refund4Freedom and #GetYourWindowsRefund.

Urge sup­pli­ers to ex­press a clear po­si­tion to­wards your rights.

Tell us your story Whether you got a re­fund or hit a road­block, share your ex­pe­ri­ence with oth­ers. Tag @fsfe and @ItalianLinuxSociety on Mastodon and use our pre-made text for your so­cial me­dia posts.

Share on Mastodon

Share on X/Twitter

Share on Facebook

If you asked for a re­fund, we can send to you some free stick­ers for your free lap­top!

To re­ceive news about the right to re­im­burse­ment of pre-in­stalled soft­ware li­cences in Italy, see: ADUC Windows re­fund page.

reuters.com

www.reuters.com

Please en­able JS and dis­able any ad blocker

nytimes.com

www.nytimes.com

Please en­able JS and dis­able any ad blocker

Gemini Omni 1.1 Flash lets you build with more control

blog.google

Aug 27, 2026

|

Omni now de­liv­ers stu­dio-qual­ity video pro­duc­tion, in­clud­ing the abil­ity to ex­tend a scene, first and last frame in­ter­po­la­tion, crisp 4K up­scal­ing, faster pro­to­typ­ing, and more.

Anish Nangia

Product Manager, Google DeepMind

Alisa Fortin

Product Manager, Google DeepMind

Your browser does not sup­port the au­dio el­e­ment.

Listen to ar­ti­cle

[[duration]] min­utes

This con­tent is gen­er­ated by Google AI. Generative AI is ex­per­i­men­tal

Today, we’re in­tro­duc­ing Gemini Omni 1.1 Flash, a new suite of cre­ative con­trols and gen­er­a­tive video ca­pa­bil­i­ties to sup­port de­vel­op­ers. Gemini Omni brought real-world rea­son­ing to gen­er­a­tive cre­ation, and to­day’s up­dates make Omni 1.1 pro­duc­tion-ready for pro­fes­sional use via the Gemini API in Google AI Studio.

Whether you’re build­ing gen­er­a­tive video work­flows, cre­ative tools, or me­dia edit­ing soft­ware, these up­dates make gen­er­a­tive video more con­trol­lable, faster to it­er­ate on, and pol­ished for real-world de­ploy­ment. Here’s a look at what’s new:

Extend scenes for longer sto­ry­telling

Scene ex­ten­sion al­lows you to take an ex­ist­ing video and con­tinue gen­er­at­ing footage seam­lessly from where it left off.

With Omni 1.1, the model can now an­a­lyze up to 10 sec­onds of prior con­text — a leap from pre­vi­ous mod­els that only ref­er­enced the fi­nal sec­ond. The re­sult is im­proved vi­sual con­sis­tency and nar­ra­tive ad­her­ence, let­ting you build longer sto­ries or branch into new cre­ative di­rec­tions. You can ex­tend videos in 10-second in­cre­ments up to a to­tal cu­mu­la­tive length of 40 sec­onds.

Here’s how you can ex­tend your scene with the Gemini API:

from google im­port genai

client = genai.Client()

in­ter­ac­tion = client.in­ter­ac­tions.cre­ate( model=“gem­ini-omni-1.1-flash”, pre­vi­ous_in­ter­ac­tion_id=pre­vi­ous_video_in­ter­ac­tion.id, in­put=[ {“type”: text”, text”: Continue the scene.“} ], re­sponse_­for­mat={ resolution”: 360p”, }, )

Specify first and last frames

Achieve smooth tran­si­tions and cam­era move­ments by spec­i­fy­ing the start­ing and end­ing frames of a shot. Omni 1.1 gen­er­ates con­tin­u­ous video be­tween two keyframes, mak­ing it ideal for com­plex cam­era or­bits, zoom tran­si­tions, or seam­less loop­ing clips.

Prompt 1: A close-up low-an­gle shot of a styl­ish drum­mer in a beige suit play­ing a red drum kit in a grand hall tran­si­tions as the cam­era whip-pans to the side, re­veal­ing an older sax­o­phon­ist play­ing along­side a bal­let dancer spin­ning in a white out­fit un­der soft pur­ple stage lights. One con­tin­u­ous shot, no jump cuts.

Prompt 2: The cam­era zooms into the TV screen, where we see the same woman and the same scene from the be­gin­ning. Seamless video. One con­tin­u­ous shot, no jump cuts.

Draft videos more ef­fi­ciently in 360p

Generate light­weight pre­views in 360p res­o­lu­tion up to 60% faster* and at a third of the cost com­pared to Omni 1.1’s stan­dard 720p res­o­lu­tion. This is help­ful for rapid pro­to­typ­ing, sto­ry­board it­er­a­tion, and quick ren­der­ing in de­vel­oper plat­forms.

*Up to 60% faster gen­er­a­tion based on sys­tem through­put of 360p vs. 720p res­o­lu­tion

Prompt: A mi­cro­scopic view of iri­des­cent ma­rine di­atoms, dis­play­ing in­tri­cate, glass-like sil­ica shells with breath­tak­ing nat­ural sym­me­try. The col­ors range from deep vol­canic am­ber and warm cop­per to vi­brant turquoise and vi­o­let, mim­ic­k­ing the rich palette of earth and ocean. Tiny, del­i­cate struc­tures glow softly against a clean dark field back­ground. High-fidelity sci­en­tific imag­ing, sharp de­tails, or­ganic tex­tures, mi­cro-pho­tog­ra­phy. Maintain the mi­cro­scope lens ef­fect through­out the en­tire video.

Upscale up to 4K res­o­lu­tion

Generate pol­ished, high-res­o­lu­tion 1080p or 4K out­puts that are ready for pro­fes­sional pro­duc­tion with Omni 1.1.

Prompt 1: Fish swim­ming, track­ing shot

Prompt 2: A lit­tle chip­munk dart­ing out of the woods from the left side of the screen and sniff­ing the air in­quis­i­tively be­fore dart­ing out of frame on the right side

Prompt 3: Cinematic macro close-up of vi­brant golden-or­ange Japanese maple leaves on a del­i­cate branch, gen­tly rustling and sway­ing in a soft, rhyth­mic au­tumn breeze. Sunlight fil­ters through the translu­cent fo­liage, cre­at­ing a warm, glow­ing ef­fect. Shallow depth of field, dreamy bokeh back­ground, hy­per-de­tailed tex­tures, pho­to­re­al­is­tic, 4k.

Add video ref­er­ences in your mul­ti­modal in­put

Reference up to three sec­onds of video when craft­ing your scene, al­low­ing you to main­tain vi­sual con­text and char­ac­ter con­sis­tency based on video ref­er­ences.

Prompt: Use the three up­loaded videos of dancers and re­place them with the pro­vided char­ac­ters. Have them per­form their in­di­vid­ual dances from the ref­er­ence videos, all to­gether in the large, open space from the pro­vided im­age.

The dog char­ac­ter dog.png should do the clas­si­cal dance from dance3.mp4. The oc­to­pus octo.png should do the hip hop dance from dance1.mp4, and the bear bear.png should do the break­dance from dance2.mp4. The fi­nal re­sult should be one con­tin­u­ous shot with no scene cuts.

Inspiring con­cepts for what you can build

Here are a few ideas show­ing how de­vel­op­ers can put these new ca­pa­bil­i­ties into ac­tion across cus­tom tools and cre­ative work­flows.

See how cus­tomers are putting Omni Flash in pro­duc­tion

Our cus­tomers are al­ready dri­ving real-world pro­duc­tion with Gemini Omni Flash via the Agent Platform API. Explore the videos they’ve cre­ated and hear about how they are us­ing the model be­low.

Build with Gemini Omni 1.1 Flash Today

Pricing table for Gemini Omni 1.1 Flash.

Omni 1.1 is rolling out across the Google de­vel­oper ecosys­tem:

Start build­ing in Google AI Studio: Try out Omni 1.1 di­rectly in Google AI Studio.

Build on Gemini Enterprise Agent Platform: Enterprises can build with Omni 1.1 di­rectly via Agent Platform API.

Explore the de­vel­oper doc­u­men­ta­tion: Check out the of­fi­cial doc­u­men­ta­tion, the cook­book and prompt­ing guides to learn how to in­te­grate scene ex­ten­sions, video ref­er­ences, and up­scal­ing into your ap­pli­ca­tions.

Omni 1.1 is also avail­able to all Google AI Plus, Pro and Ultra sub­scribers glob­ally in Google Flow, start­ing to­day. Scene ex­ten­sion is avail­able to all Google AI Plus, Pro and Ultra sub­scribers glob­ally in the Gemini app.

Get the lat­est news from Google in your in­box

Sign up for our newslet­ters with prod­uct up­dates, event in­for­ma­tion, spe­cial of­fers, and more.

Your in­for­ma­tion will be used in ac­cor­dance with Google’s pri­vacy pol­icy. You may opt out at any time.

Integer Divide-by-Zero in `vpk_read_packet` (VPK Demuxer)

code.ffmpeg.org

Hello.

This is a bug found with our fuzzer: https://​github.com/​daedalus/​fuzzer/

File: libav­for­mat/​vpk.c:89 Severity: Medium — crafted 21-byte in­put crashes any FFmpeg-based ap­pli­ca­tion that opens a ma­li­cious .vpk file or stream Root cause: vp­k_read­_­packet di­vides vpk->last_block­_­size by par->ch_lay­out.nb_chan­nels with­out check­ing whether nb_chan­nels is zero. A mal­formed VPK header can set nb_chan­nels = 0, caus­ing SIGFPE on the di­vi­sion.

Description

The Sony PS2 VPK de­muxer (libavformat/vpk.c) reads au­dio blocks from a cus­tom con­tainer for­mat. In vp­k_read­_­packet, the last block of the stream is han­dled spe­cially:

if (vpk->current_block == vpk->block­_­count) { un­signed size = vpk->last_block­_­size / par->ch_lay­out.nb_chan­nels; un­signed skip = (par->block_align - vpk->last_block­_­size) / par->ch_lay­out.nb_chan­nels; … }

Both size and skip di­vide by par->ch_lay­out.nb_chan­nels. When nb_chan­nels is zero, the CPU raises SIGFPE (integer di­vide-by-zero ex­cep­tion).

Trigger Chain

Demuxer probe (vpk_probe) matches the VPK big-en­dian magic and as­signs the in­put to the VPK de­muxer.

vp­k_read­_­header parses the 24-byte header. The fuzz in­put sets nb_chan­nels = 0 at header bytes 0x0e–0x11. vp­k_read­_­header does val­i­date nb_chan­nels > 0, but in the fuzzer’s cus­tom-AVIO path the probe/​header data and the later packet-read data can di­verge: by the time vp­k_read­_­packet runs, par->ch_lay­out.nb_chan­nels has re­verted to 0 from the orig­i­nal fuzz stream while vpk->last_block­_­size and vpk->block­_­count were com­puted from probe data with a valid chan­nel count. The di­vi­sion is there­fore reached with a live-but-zero di­vi­sor.

vp­k_read­_­packet reaches the fi­nal-block branch and di­vides by zero on both size and skip.

Crash Input

Hex dump of the 21-byte crash in­put (crash_1787378545_34bc062c_sig_signal8.bin):

00000000 20 4b 50 56 56 50 00 f8 04 00 3b 03 61 39 56 32 | KPVVP….;.a9V2| 00000010 36 36 30 38 50 |6608P|

Bytes 0 – 3: 20 4b 50 56 — ASCII KPV, which is the VPK big-en­dian magic VPK byte-re­versed across a word bound­ary

Byte 0x0e–0x11: 00 00 00 00 — nb_chan­nels = 0, the crash trig­ger

GDB Backtrace

Program re­ceived sig­nal SIGFPE, Arithmetic ex­cep­tion. 0x00005555557a9877 in vp­k_read­_­packet (s=0x555557fed700, pkt=0x555557fed300) at libav­for­mat/​vpk.c:89 89 un­signed size = vpk->last_block­_­size / par->ch_lay­out.nb_chan­nels;

#0 vp­k_read­_­packet #1 ff_read­_­packet #2 read­_frame_in­ter­nal #3 av_read­_frame #4 fuz­z_ffm­peg #5 main

Crash Metadata

Exploitability Assessment

The di­vide-by-zero is a de­nial-of-ser­vice prim­i­tive. There is no con­trolled write or ar­bi­trary read ad­ja­cent to the fault­ing in­struc­tion. The in­put can be em­bed­ded in a .vpk file or a con­tainer that iden­ti­fies it­self as VPK to trig­ger the crash in any FFmpeg-linked ap­pli­ca­tion.

Suggested Fix

Add a guard at the top of vp­k_read­_­packet to re­ject zero-chan­nel streams cleanly:

sta­tic int vp­k_read­_­packet(AV­For­mat­Con­text *s, AVPacket *pkt) { AVCodecParameters *par = s->streams[0]->codec­par; VPKDemuxContext *vpk = s->priv_­data; int ret, i;

if (par->ch_layout.nb_channels == 0) re­turn AVERROR_INVALIDDATA;

vpk->cur­ren­t_block++; … }

This is con­sis­tent with the ex­ist­ing val­i­da­tion in vp­k_read­_­header (if (st->codecpar->ch_layout.nb_channels <= 0) re­turn AVERROR_INVALIDDATA;) and re­turns a clean er­ror in­stead of SIGFPE.

Regression Test

/* Trigger: 21-byte VPK stream with nb_chan­nels=0 — SIGFPE in vpk.c:89 */ sta­tic const un­signed char vp­k_crash[] = { 0x20, 0x4b, 0x50, 0x56, 0x56, 0x50, 0x00, 0xf8, 0x04, 0x00, 0x3b, 0x03, 0x61, 0x39, 0x56, 0x32, 0x36, 0x36, 0x30, 0x38, 0x50 };

/* Expect: av_read­_frame re­turns -22 (AVERROR_INVALIDDATA), does not crash */

Hello.

This is a bug found with our fuzzer: https://​github.com/​daedalus/​fuzzer/

**File**: `libavformat/vpk.c:89` **Severity**: Medium — crafted 21-byte in­put crashes any FFmpeg-based ap­pli­ca­tion that opens a ma­li­cious `.vpk` file or stream **Root cause**: `vpk_read_packet` di­vides `vpk->last_block_size` by `par->ch_layout.nb_channels` with­out check­ing whether `nb_channels` is zero. A mal­formed VPK header can set `nb_channels = 0`, caus­ing `SIGFPE` on the di­vi­sion.

### Description

The Sony PS2 VPK de­muxer (`libavformat/vpk.c`) reads au­dio blocks from a cus­tom con­tainer for­mat. In `vpk_read_packet`, the last block of the stream is han­dled spe­cially:

```c if (vpk->current_block == vpk->block­_­count) { un­signed size = vpk->last_block­_­size / par->ch_lay­out.nb_chan­nels; un­signed skip = (par->block_align - vpk->last_block­_­size) / par->ch_lay­out.nb_chan­nels; … } ```

Both `size` and `skip` di­vide by `par->ch_layout.nb_channels`. When `nb_channels` is zero, the CPU raises `SIGFPE` (integer di­vide-by-zero ex­cep­tion).

### Trigger Chain

1. **Demuxer probe** (`vpk_probe`) matches the `VPK ` big-en­dian magic and as­signs the in­put to the VPK de­muxer. 2. **`vpk_read_header`** parses the 24-byte header. The fuzz in­put sets `nb_channels = 0` at header bytes `0x0e`–`0x11`. `vpk_read_header` does val­i­date `nb_channels > 0`, but in the fuzzer’s cus­tom-AVIO path the probe/​header data and the later packet-read data can di­verge: by the time `vpk_read_packet` runs, `par->ch_layout.nb_channels` has re­verted to `0` from the orig­i­nal fuzz stream while `vpk->last_block_size` and `vpk->block_count` were com­puted from probe data with a valid chan­nel count. The di­vi­sion is there­fore reached with a live-but-zero di­vi­sor. 3. **`vpk_read_packet`** reaches the fi­nal-block branch and di­vides by zero on both `size` and `skip`.

### Crash Input

Hex dump of the 21-byte crash in­put (`crash_1787378545_34bc062c_sig_signal8.bin`):

``` 00000000 20 4b 50 56 56 50 00 f8 04 00 3b 03 61 39 56 32 | KPVVP….;.a9V2| 00000010 36 36 30 38 50 |6608P| ```

- Bytes 0 – 3: `20 4b 50 56` — ASCII `” KPV”`, which is the VPK big-en­dian magic `VPK ` byte-re­versed across a word bound­ary - Byte 0x0e–0x11: `00 00 00 00` — `nb_channels = 0`, the crash trig­ger

### GDB Backtrace

``` Program re­ceived sig­nal SIGFPE, Arithmetic ex­cep­tion. 0x00005555557a9877 in vp­k_read­_­packet (s=0x555557fed700, pkt=0x555557fed300) at libav­for­mat/​vpk.c:89 89 un­signed size = vpk->last_block­_­size / par->ch_lay­out.nb_chan­nels;

#0 vp­k_read­_­packet #1 ff_read­_­packet #2 read­_frame_in­ter­nal #3 av_read­_frame #4 fuz­z_ffm­peg #5 main ```

### Crash Metadata

| Field | Value | |–-|–-| | Signal | `SIGFPE` (returncode −8) | | Fault ad­dress / RIP | `0x7ffff48a66d7` (instruction it­self) | | RSP | `0x7fffffffcce0` | | Execs to find | 495,211 | | Corpus at find | 13,188 en­tries | | Elapsed | 10 h 43 m | | Parent seed | `36e65f4009ba0cab` | | Target SHA256 | `d704c2a52b21bd33` |

### Exploitability Assessment

| Factor | Assessment | |–-|–-| | Crash de­ter­min­ism | **Deterministic** — 21 bytes, sin­gle de­muxer code path | | Trigger depth | Shallow — `avformat_open_input` auto-de­tects for­mat from magic | | Preconditions | None — in­put is self-con­tained, no net­work, no heap setup | | Signal type | SIGFPE (integer di­vide-by-zero), not mem­ory cor­rup­tion | | Memory safety | No OOB read/​write, no use-af­ter-free, no NULL deref­er­ence | | Reach | Any ap­pli­ca­tion that calls `avformat_open_input` + `av_read_frame` on un­trusted data | | Severity | **Medium** — re­li­able DoS; not an im­me­di­ate code-ex­e­cu­tion prim­i­tive |

The di­vide-by-zero is a **denial-of-service** prim­i­tive. There is no con­trolled write or ar­bi­trary read ad­ja­cent to the fault­ing in­struc­tion. The in­put can be em­bed­ded in a `.vpk` file or a con­tainer that iden­ti­fies it­self as VPK to trig­ger the crash in any FFmpeg-linked ap­pli­ca­tion.

### Suggested Fix

Add a guard at the top of `vpk_read_packet` to re­ject zero-chan­nel streams cleanly:

```c sta­tic int vp­k_read­_­packet(AV­For­mat­Con­text *s, AVPacket *pkt) { AVCodecParameters *par = s->streams[0]->codec­par; VPKDemuxContext *vpk = s->priv_­data; int ret, i;

if (par->ch_layout.nb_channels == 0) re­turn AVERROR_INVALIDDATA;

vpk->cur­ren­t_block++; … } ```

This is con­sis­tent with the ex­ist­ing val­i­da­tion in `vpk_read_header` (`if (st->codecpar->ch_layout.nb_channels <= 0) re­turn AVERROR_INVALIDDATA;`) and re­turns a clean er­ror in­stead of `SIGFPE`.

### Regression Test

```c /* Trigger: 21-byte VPK stream with nb_chan­nels=0 — SIGFPE in vpk.c:89 */ sta­tic const un­signed char vp­k_crash[] = { 0x20, 0x4b, 0x50, 0x56, 0x56, 0x50, 0x00, 0xf8, 0x04, 0x00, 0x3b, 0x03, 0x61, 0x39, 0x56, 0x32, 0x36, 0x36, 0x30, 0x38, 0x50 };

/* Expect: av_read­_frame re­turns -22 (AVERROR_INVALIDDATA), does not crash */ ```

Luanti removed from Google Play due to baseless AI copyright notice

blog.luanti.org

Luanti’s Android app is cur­rently not avail­able on the Google Play Store due to a base­less DMCA no­tice filed on be­half of Microsoft by Tracer.AI, al­leg­ing that Luanti in­fringes Minecraft’s copy­right. The Luanti app does not con­tain any pro­pri­etary code or as­sets, from Minecraft or oth­er­wise.

We re­ceived a sim­i­lar no­tice from the same com­pany in 2023 and suc­cess­fully ap­pealed against it. This com­pany also filed a sim­i­lar no­tice this year against an in­die game with sim­i­lar voxel art style by the name of Allumeria.

Table of Contents

What is Luanti?

What is the DMCA no­tice?

Which as­sets?

Cubes are for every­one

What is Tracer.AI?

This is not the first time this has hap­pened

This can’t keep hap­pen­ing

What next?

What is Luanti?

Luanti is a voxel game-cre­ation plat­form where any­one can make, share, dis­cover, and play blocky games. It does not ship with any games or game as­sets by de­fault. Instead, play­ers can browse a cat­a­log of games cre­ated by the com­mu­nity, or sim­ply join mul­ti­player servers.

We are a non-profit pro­ject de­vel­oped by a com­mu­nity of pas­sion­ate in­di­vid­u­als ex­press­ing their cre­ativ­ity. Luanti is open source, which means any­one can view the source code, mod­ify it, learn from it, re­dis­trib­ute it, and even sell games made with it on plat­forms like Steam.

While Luanti is pop­u­lar as an open-source al­ter­na­tive to Minecraft (as its roots are in blocky sand­box games), it also low­ers bar­ri­ers to bring­ing cre­ative ideas to life. The free­dom and cus­tomiza­tion Luanti af­fords has made it an ex­cel­lent tool in ed­u­ca­tion, find­ing its way into many schools across Europe.

What is the DMCA no­tice?

The Digital Millennium Copyright Act (DMCA) is United States law which lays out a no­tice-and-take­down process which plat­forms like Google Play fol­low to avoid li­a­bil­ity for dam­ages re­sult­ing from copy­right-in­fring­ing pack­ages which they dis­trib­ute. These plat­forms are not re­spon­si­ble for the ac­tions of their users, but they are re­spon­si­ble for tak­ing cor­rec­tive ac­tion when user-gen­er­ated con­tent is re­ported.

The DMCA no­tice we re­ceived through Google claims that:

These prod­ucts use copy­righted as­sets as out­lined di­rectly from the Minecraft game (available at www.minecraft.net) with­out au­tho­riza­tion and should be re­moved. Specifically, US Reg. #TX 8 – 192-097

These prod­ucts use copy­righted as­sets as out­lined di­rectly from the Minecraft game (available at www.minecraft.net) with­out au­tho­riza­tion and should be re­moved. Specifically, US Reg. #TX 8 – 192-097

US Reg. #TX 8 – 192-097” is the reg­is­tra­tion of Minecraft Java Edition 1.9 with the US Copyright Office.

It does not pro­vide any in­for­ma­tion aside from this and does not out­line which as­sets Luanti al­legedly uses.

Which as­sets?

Engine

Luanti is a game-cre­ation plat­form and does not ship with any games, let alone game as­sets. In fact, here are all the tex­tures Luanti comes with:

Luanti also in­cludes fur­ther as­sets, par­tic­u­larly fonts. These are prop­erly at­trib­uted in the li­cense file.

The GitHub repos­i­tory does in­clude the Development Test game, which is also avail­able on ContentDB but is not in­cluded in Luanti re­leases any­more. Being a test­ing ground for the en­gine, the tex­tures are largely util­i­tar­ian in na­ture.

Minetest Game

Luanti pre­vi­ously shipped with Minetest Game, a craft­ing sur­vival game in­ten­tion­ally kept bare-bones to pro­vide a base for mod­ding. As of December 2023, it is no longer bun­dled with Luanti, and can be down­loaded from within the Luanti client like any other game. All of Minetest Game’s as­sets are orig­i­nal and prop­erly li­censed1.

Third-party con­tent

Players can down­load con­tent from ContentDB, our in-app game cat­a­log. Except for Minetest Game and Development Test, all these games, mods, and tex­ture packs are third-party, just like most apps on Google Play.

Packages up­loaded on ContentDB are re­viewed man­u­ally by vol­un­teer staff be­fore they are ap­proved. We proac­tively check for copy­right is­sues, in­clud­ing check­ing for com­mer­cial as­sets. Independent of this in­ci­dent, we have been look­ing into au­to­mated as­set flag­ging us­ing con­ven­tional per­cep­tual hash­ing al­go­rithms. This would help hu­man mod­er­a­tors de­tect copy­righted as­sets, and we will al­ways re­quire a fi­nal hu­man de­ci­sion with­out re­ly­ing on er­ro­neous AI.

It is in every­one’s best in­ter­ests that con­tent on ContentDB is le­gal and free, as it al­lows the com­mu­nity to safely use and build on top of it for their own pro­jects. If you are a right­sh­older who be­lieves your rights are be­ing in­fringed by con­tent hosted on ContentDB, then the cor­rect ac­tion is to sub­mit a DMCA no­tice against the par­tic­u­lar game on ContentDB.

Cubes are for every­one

The con­cept of a game fea­tur­ing 3D cubes or vox­els is not some­thing any­one can own2. Minecraft was orig­i­nally in­spired by the 2009 game Infiniminer which uses sim­i­lar voxel graph­ics, and later ex­am­ples like Hytale show that block games make up an en­tire genre that Minecraft is sim­ply a part of. Mojang and its par­ent com­pany Microsoft have all rights to en­force their copy­right for as­sets such as Minecraft’s tex­tures, but can­not use the DMCA as a means to in­tim­i­date and mo­nop­o­lize an en­tire genre of games.

Luanti was orig­i­nally cre­ated by celeron55 in 2010 un­der the name Minetest”, in­spired by the newly-re­leased Minecraft Alpha to make a sand­box in a voxel grid that ran bet­ter on low-end hard­ware. Work be­gan in 2011 on a mod­ding API us­ing the Lua pro­gram­ming lan­guage, al­low­ing play­ers to cre­ate their own con­tent. Minetest has con­tin­ued to work to sup­port a larger va­ri­ety of user cre­ativ­ity ever since. In 2024, the re­name from Minetest to Luanti set this di­rec­tion in stone.

What is Tracer.AI?

Quoting their web­site:

Tracer is a next-gen­er­a­tion brand pro­tec­tion plat­form that em­pow­ers brands to take con­trol of their brand pres­ence on­line. Our AI agents stream­line work­flows and en­hance op­er­a­tional ef­fi­ciency, mak­ing it eas­ier to mon­i­tor dig­i­tal chan­nels, take down de­tec­tions, and an­a­lyze vast amounts of data to pro­vide bet­ter busi­ness in­tel­li­gence in­sights. Bring speed, ac­cu­racy, and ef­fi­ciency to your brand pro­tec­tion strat­egy, with­out drain­ing your team’s re­sources.

Tracer’s AI brand pro­tec­tion tech­nol­ogy de­tects and re­moves in­fringe­ments to your brand across thou­sands of dig­i­tal plat­forms, faster and more ac­cu­rately than ever be­fore.

Tracer is a next-gen­er­a­tion brand pro­tec­tion plat­form that em­pow­ers brands to take con­trol of their brand pres­ence on­line. Our AI agents stream­line work­flows and en­hance op­er­a­tional ef­fi­ciency, mak­ing it eas­ier to mon­i­tor dig­i­tal chan­nels, take down de­tec­tions, and an­a­lyze vast amounts of data to pro­vide bet­ter busi­ness in­tel­li­gence in­sights. Bring speed, ac­cu­racy, and ef­fi­ciency to your brand pro­tec­tion strat­egy, with­out drain­ing your team’s re­sources.

Tracer’s AI brand pro­tec­tion tech­nol­ogy de­tects and re­moves in­fringe­ments to your brand across thou­sands of dig­i­tal plat­forms, faster and more ac­cu­rately than ever be­fore.

From this, we can gather that Tracer uses AI agents for au­to­mated in­fringe­ment de­tec­tion. In a 2024 blog post, the com­pany boasts 85% faster take­downs”, 100% more re­views month-over-month” along with review times that are six times faster than tra­di­tional meth­ods”. It claims this has re­sulted in 44% more take­downs month-over-month”.

This is not the first time this has hap­pened

Luanti’s Android app re­ceived a sim­i­lar no­tice from the same com­pany in March 2023. As the no­tice was in­cor­rect, we sub­mit­ted a counter-no­tice and the app was even­tu­ally re­in­stated… af­ter 46 days3. Section 512(g)(2)(c) of the DMCA re­quires that providers [replace] the re­moved ma­te­r­ial and [cease] dis­abling ac­cess to it not less than 10, nor more than 14, busi­ness days fol­low­ing re­ceipt of the counter no­tice”. Google’s fail­ure to ad­here to the dead­lines spec­i­fied by the DMCA raises ques­tions re­gard­ing its ap­proach to­ward han­dling DMCA counter-no­tices.

In February of this year, an in­die game called Allumeria also re­ceived a DMCA take­down from Tracer.AI on be­half of Microsoft, re­sult­ing in the game’s tem­po­rary re­moval from the Steam store. The no­tice was even­tu­ally dropped by Microsoft af­ter pub­lic noise.

This can’t keep hap­pen­ing

If a com­pany can re­peat­edly sub­mit the same DMCA no­tice with no ex­pla­na­tion or ev­i­dence, tak­ing pro­jects down for months at a time, the sys­tem is bro­ken. It pre­vents users from dis­cov­er­ing or up­dat­ing Luanti, and risks users set­tling for shady or ad-rid­den forks in­stead.

If we were a small com­pany re­ly­ing on in­come from the app, this would be es­pe­cially dev­as­tat­ing. We, like most open-source com­mu­ni­ties, lack the re­sources to con­tin­u­ally fight un­founded DMCA no­tices.

What next?

We have sub­mit­ted a counter-no­tice and the app should be re­stored soon, hope­fully sooner than 46 days. But with counter-no­tices not be­ing re­spected in the set time­frame, a more pub­lic ap­proach is re­quired.

We call on Microsoft, Mojang, and Tracer.AI to stop re­ly­ing on AI tools to send in­ac­cu­rate and vague DMCA no­tices. Detection must be ver­i­fied by a hu­man and, more im­por­tantly, sub­stan­ti­ated with tan­gi­ble proof.

We call on Google to im­prove how they ver­ify no­tices, al­low users to re­spond to no­tices with­out tak­ing apps down for ex­tended pe­ri­ods of time, and prop­erly com­ply with copy­right law.

While we hope Google re­in­states the Luanti app in a timely man­ner, we would like to men­tion that the Luanti Android app is also avail­able on F-Droid, an app store for Android whose of­fi­cial repos­i­tory con­tains only ver­i­fied free soft­ware. In ad­di­tion, APK down­loads are avail­able on our own web­site. Unfortunately, both dis­tri­b­u­tion mech­a­nisms are in­creas­ingly un­der threat.

We ask our com­mu­nity and read­ers to share this post far and wide, to help raise aware­ness and en­sure this does­n’t hap­pen again, for us or any­one else.

Minetest Game’s LICENSE.txt ↩

Minetest Game’s LICENSE.txt ↩

17 U.S. Code § 102(b) https://​www.law.cor­nell.edu/​us­code/​text/​17/​102 ↩

17 U.S. Code § 102(b) https://​www.law.cor­nell.edu/​us­code/​text/​17/​102 ↩

We sub­mit­ted the counter no­tice on 25 March 2023 and the app was re­in­stated on 10 May 2023. ↩

We sub­mit­ted the counter no­tice on 25 March 2023 and the app was re­in­stated on 10 May 2023. ↩

To add this web app to your iOS home screen tap the share button and select "Add to the Home Screen".

10HN is also available as an iOS App

If you visit 10HN only rarely, check out the the best articles from the past week.

Visit pancik.com for more.