2 पॉइंट द्वारा GN⁺ 2024-12-22 | 1 टिप्पणियां | WhatsApp पर शेयर करें
  • Scylla मौजूदा C को unsafe Rust में ले जाकर बाद में ठीक करने के बजाय, मूल C को क्रमिक रूप से संरचित करके उसे सीधे safe Rust में compile करने योग्य रास्ता प्रस्तावित करता है
  • लक्ष्य applicative C subset है, जिसमें data processing, pointer operations, structured control flow और portable code शामिल हैं, जबकि goto, integer-pointer cast, pointer tricks, bitfields, और untagged union पर निर्भर code को बाहर रखा गया है
  • रूपांतरण 2 चरणों में होता है: पहले Clang AST को Mini-C में lower किया जाता है, फिर उसे safe Rust में बदला जाता है; इस दौरान integer promotion, implicit conversion, assignment expression, और prefix/postfix increment जैसे C के सूक्ष्म व्यवहारों को स्पष्ट किया जाता है
  • सबसे कठिन pointer arithmetic को Rust slice और split_at_mut/split_at आधारित splitting में बदला जाता है, और साथ ही mutability inference, trait derivation, तथा Box और borrow के चयन को भी संभाला जाता है
  • Windows SymCrypt, HACL★, bzip2 का core compression algorithm, EverParse CBOR parser/serializer, और Microsoft FrodoKEM के कुछ हिस्सों का मूल्यांकन किया गया, और रूपांतरण के दौरान bzip2 तथा FrodoKEM में undefined behavior भी मिला

Scylla द्वारा चुना गया C→Rust migration path

  • मौजूदा C code को Rust में ले जाने की प्रेरणा memory safety समस्याओं से शुरू होती है
    • Google और Microsoft के शोध का अनुमान है कि 70% security vulnerabilities गलत memory handling से जुड़ी होती हैं
    • कंपनियां और सरकारें safety-critical systems में Rust जैसी memory-safe language के उपयोग की सिफारिश कर रही हैं
  • Rust नए code के लिए स्पष्ट लाभ देता है, लेकिन पहले से test और debug किए गए industrial C codebase को पूरा का पूरा फिर से लिखना कठिन है
  • मौजूदा C→Rust automatic translation tools पूरे C को support करने के लिए आम तौर पर unsafe Rust output करते हैं
    • वे unchecked pointer या Rust transmutation जैसे C-शैली idioms की अनुमति देते हैं
    • इससे static memory safety guarantee खत्म हो जाती है और safe language इस्तेमाल करने का उद्देश्य कमजोर पड़ जाता है
  • सामान्य workflow यह है कि unsafe Rust output को शुरुआती बिंदु बनाया जाए और फिर उसे बार-बार refactor करके safe Rust में बदला जाए
    • raw pointer को safe Rust borrow में बदलने या low-level representation से Rust abstraction को पुनर्स्थापित करने के लिए static analyses प्रस्तावित की गई हैं
    • refactoring tools बिखरे हुए हैं, और c2rust refactor का support भी 2022 में बंद हो गया
  • Scylla generated unsafe Rust को ठीक करने के बजाय, मूल C code को ही क्रमिक रूप से संरचित करके उसे safe Rust में compile करने योग्य बनाने का तरीका अपनाता है

समर्थित C subset और बाहर रखे गए patterns

  • Scylla का लक्ष्य अनुमानित रूपांतरण और स्रोत C के करीब Rust code बनाना है
  • इसका target applicative C subset है
    • data को manipulate और process करने वाला code
    • pointer arithmetic इस्तेमाल करने वाला code
    • structured control flow वाला code
    • portable code
  • जो codebase निम्न patterns पर निर्भर हैं, वे supported नहीं हैं
    • goto
    • integer-pointer cast के जरिए object representation का उपयोग
    • pointer tricks
    • bitfields
    • untagged union
  • developer Scylla की समझ के अनुसार C source पर targeted rewrites और annotations लागू कर सकते हैं
    • Rust borrow checker के अनुकूल न होने वाले aliasing patterns को फिर से लिखा जा सकता है
    • tagged union को high-level ADT में translate किया जाना चाहिए, यह जानकारी Scylla को दी जा सकती है

Mini-C: C की अस्पष्टता कम करने वाली intermediate language

  • Scylla Clang frontend AST से शुरू होकर पहले Mini-C नाम की एक language में रूपांतरण करता है
  • Mini-C, C की तरह branching, loops, pointers, dereference, और address-of को संभालता है, लेकिन इसकी semantics “no-surprises” हैं
    • सभी integers fixed width के होते हैं
    • C के integer promotion और integer conversion को explicit cast के रूप में दिखाया जाता है
    • void * जैसे untyped pointers की अनुमति नहीं है
  • Mini-C, C से अलग, एक expression language है
    • assignment कोई value return नहीं करता
    • e1 = e2 = e3, p[i++] जैसे C syntax को Mini-C में desugar किया जाता है
    • loop और conditional के test expressions का type C के int की जगह bool होना चाहिए
  • Clang के typed AST को Mini-C typed AST में ले जाते समय C के implicit behaviors को explicit बनाया जाता है
    • conditional expressions को bool के अनुसार ढाला जाता है
    • array indexing को size_t के अनुसार ढाला जाता है
    • function call arguments और assignment के right-hand side की implicit conversions को explicit cast में बदला जाता है
    • arithmetic operations में C standard की usual arithmetic conversions को दर्शाया जाता है
  • रूपांतरण यह मानकर चलता है कि C code portable है और C data model पर निर्भर नहीं है
    • उदाहरण के लिए, ऐसा code अपेक्षित नहीं है जिसका व्यवहार long के 4-byte या 8-byte होने पर बदल जाए
    • implementation configure-time पर target architecture का data model detect करके unsigned int को uint32_t जैसे fixed-width types में बदलती है

ADT और tuple synthesis

  • Mini-C, C से ऊंचे स्तर के ADT, tuple, और pattern matching प्रदान करता है
  • tagged union को annotations के जरिए ADT में translate किया जाता है
    • target form { int tag; union { t0 case0; ...; tn caseN }} जैसी संरचना है
    • यह माना जाता है कि tag value 0 से N तक हैं और tag value union case के क्रम से मेल खाती है
  • Scylla annotated tagged union types को variant types में बदलता है
    • value construction के समय यह जांचता है कि .tag = i और .casej = e मेल खाते हैं या नहीं
    • अगर मेल खाते हैं, तो उन्हें संबंधित constructor value में बदला जाता है
    • payload और tag मेल न खाने पर Mini-C में translate नहीं किया जाता
  • tagged union field access को सुरक्षित होने के लिए current tag state की जानकारी चाहिए
    • if (x.tag == i) { ... x.casei } या switch जैसे patterns पहचाने जाते हैं
    • इन्हें match x with | Ci v -> ... रूप में बदला जाता है
    • अन्य union case access को invalid माना जाता है और translation error दिया जाता है
  • tuple भी annotations के जरिए synthesize किए जा सकते हैं
    • n fields वाले struct को n-ary tuple में बदला जाता है
    • field access को tuple field access में बदला जाता है
    • tuple संरचनात्मक रूप से typed होते हैं, इसलिए mut-polymorphism का लाभ मिलता है

Mini-C से safe Rust में रूपांतरण

  • Mini-C, complete type annotations के साथ C program का प्रतिनिधित्व देता है, और फिर इसे safe Rust में बदला जाता है
  • तीन मुख्य कठिनाइयां हैं
    • C की pointer arithmetic हटाना
    • mutability और aliasing को स्पष्ट करना
    • trait जैसी Rust idiomatic structures को अपने-आप उपलब्ध कराना
  • pointer type conversion, Rust की pointer representation के अंतर के कारण जटिल है
    • Rust Box<T> और &T में अंतर करता है
    • single-element pointer और multi-element pointer भी &T और &[T] की तरह अलग होते हैं
    • Rust arrays values होते हैं और C की तरह अपने-आप pointer में decay नहीं होते
  • बुनियादी रणनीति यह है कि C के सभी pointer types को Rust के slice borrow &[T] में compile किया जाए
    • stack pointer और heap pointer, दोनों डिफ़ॉल्ट रूप से slice borrow बनते हैं
    • single-element और multi-element pointers भी डिफ़ॉल्ट रूप से slice borrow बनते हैं
    • mutability का अनुमान बाद के अलग चरण में अपने-आप लगाया जाता है
  • Scylla heuristics और manual annotations की मदद से कुछ pointers को Box<T> में translate करता है
    • T *create() जैसी function, जिसे global reference के बिना fresh allocation माना जाए, fn create() -> Box<T> में translate की जा सकती है
    • यह analysis struct और variant definitions के अंदर तक fixpoint शैली में recursively लागू होता है
    • जिन struct में borrow बचते हैं, उनमें lifetime parameter जोड़े जाते हैं

Box, slice, और array conversion की सीमाएं

  • Rust में array, slice borrow, और Box के बीच explicit conversions की ज़रूरत होती है, इसलिए Scylla का Rust translation भी type-directed तरीके से चलता है
  • conversion rules array या boxed slice को slice borrow में बदलने के लिए coercion insert करते हैं
    • array, &x[..] जैसे रूप में slice borrow बन जाता है
    • boxed slice को borrow में बदला जा सकता है
  • उल्टी दिशा में conversion भी संभव है
    • slice या array को heap allocation में promote करके Box<[T]> में बदला जा सकता है
  • यह reverse conversion copy semantics में अंतर पैदा कर सकता है
    • C में array और pointer एक ही memory की ओर इशारा कर सकते हैं
    • Rust में Box::new(x) संभव है कि x की copy बना दे
    • integer array जैसे basic type arrays में Copy trait से opt out करने का तरीका नहीं है, इसलिए Rust चुपचाप copy कर सकता है
  • Scylla ऐसे conversion होने पर मूल variable को environment से हटा देता है ताकि बाद में उसका उपयोग न हो सके
    • अगर मूल C program उस variable का आगे भी उपयोग करता है, तो translation error आता है
    • developer को रूपांतरण से पहले C source code को ठीक करके अपने इरादे को अधिक स्पष्ट करना पड़ता है

Pointer arithmetic को Rust slice splitting में बदलना

  • C programs अक्सर arrays को केवल एक base pointer से access नहीं करते, बल्कि उन्हें chunks में बांटते हैं या current-position pointer बनाए रखकर traverse करते हैं
  • Rust arbitrary pointer arithmetic की अनुमति नहीं देता, बल्कि split_at_mut या split_at के जरिए slice को बांटने का तरीका देता है
    • split_at_mut ऐसा primitive है जिसमें मूल slice का ownership छोड़कर दो sub-slice मिलते हैं
    • इससे Rust का invariant बना रहता है कि mutable data का unique owner होना चाहिए
  • Scylla, C pointer arithmetic को Rust के splitting approach से मिलाने के लिए split tree पेश करता है
    • हर C pointer को एक split tree पर map किया जाता है
    • split tree flow-dependent रूप से बदलता है
    • यह track करता है कि program के किसी बिंदु पर C pointer access को किस Rust slice access में बदलना है
  • क्योंकि C pointers में length information नहीं होती, Scylla मानता है कि chunks आपस में overlap नहीं करते
    • अगर overlap इरादतन है, तो Rust type checking पास नहीं होगी और developer को C code फिर से लिखना पड़ेगा
    • रूपांतरण अनुमानित रहना चाहिए, इसलिए backtracking से बचते हुए forward तरीके से किया जाता है
  • उदाहरण में 32-byte array abcd को 8-byte के चार limb क्षेत्रों में बांटा जाता है
    • C में abcd + 0, abcd + 16, abcd + 8, abcd + 24 जैसी pointer arithmetic होती है, जो left-to-right क्रम में नहीं है
    • Rust translation, split_at_mut calls के इतिहास को split tree के रूप में बनाए रखकर सही sub-slice ढूंढता है

मूल्यांकन के targets और मिले undefined behavior

  • Scylla implementation, Clang का उपयोग करके मौजूदा C code को input के रूप में लेती है और safe Rust output करती है
  • मूल्यांकन में कई मौजूदा C projects के कुछ हिस्से शामिल थे
    • Windows का SymCrypt का कुछ भाग
    • HACL★ cryptographic library का कुछ भाग
    • bzip2 compression algorithm का core भाग
    • EverParse library का CBOR binary parser और serializer
    • Microsoft के FrodoKEM post-quantum cryptographic primitive implementation का कुछ भाग
  • ये उदाहरण दिखाते हैं कि Scylla का applicative C subset कई security-sensitive applications को समेट सकता है
  • रूपांतरण के दौरान bzip2 और FrodoKEM के मूल C code में मौजूद undefined behavior की पहचान कर उसे रिपोर्ट भी किया गया

1 टिप्पणियां

 
GN⁺ 2024-12-22
Hacker News राय
  • यह बात अहम है कि यह काम “पहले से formal verification किए गए C codebase” को target करता है
    आम system C code आम तौर पर formal verification किया हुआ नहीं होता, इसलिए यह काफी अलग मामला है

    • फिर भी यह पूरी तरह भरोसेमंद नहीं लगता। पेपर के सेक्शन 2.2 में भी कहा गया है कि transformation rules द्वारा लाए गए coercions subtle semantic differences पैदा कर सकते हैं
      उदाहरण के लिए, C में stack पर मौजूद array की ओर इशारा करने वाला pointer Rust में Box<[u8]> के रूप में translate हो सकता है, यानी नए heap copy का ownership रखने वाला pointer। अगर original code इस तथ्य पर निर्भर था कि pointer असली array को ही point करता है, तो translated code चुपचाप गलत behave कर सकता है
      मेरे project scpptool में memory-safe C++ subset की automatic translation feature होती, तो वह arrays को replacement types और iterators में ले जाकर original semantics बनाए रखने जैसे तरीके से handle करती
      OP project शायद केवल उस C को handle करता है जिसे safe Rust में बदलना आसान है, लेकिन समस्या की कठिनाई देखते हुए उपलब्धि सम्मानयोग्य है और कुछ हद तक उपयोगी भी लगती है
    • इसमें caveats बहुत ज्यादा हैं, और यह लगभग hype जैसा है
      असल में इन्होंने वास्तविक C translate नहीं किया, बल्कि F* में लिखे code को इस तरह बदला कि C compiler की तरफ से Rust output निकले। इन्होंने complex real-world C code का सामना नहीं किया; ज्यादा से ज्यादा उन्होंने एक restricted Mini-C handle किया है, जैसा कोई toy compiler output कर सकता है
      मूल लेख में भी कहा गया है कि अगर original C program x पर और ज्यादा depend करे तो translation error देगी और programmer से source modify करने को कहेगी, जिसका मतलब है कि वे उम्मीद करते हैं कि C पहले से Rust borrow checker को satisfy करने वाले style में लिखा हो
      यह academic अंदाज की बात लगती है: “Figure 4 में सुंदर rules दिखाए गए हैं, लेकिन actual implementation ढेरों hacks पर निर्भर है”
      इससे भी खराब यह है कि statically distinguishable overlap पर compile error आएगा, और नहीं तो Rust code runtime में panic कर सकता है। formal verification किए गए C program को “अब crash भी हो सकने वाले” Rust program में बदलना अजीब है
      HACL* को मौजूदा formally verified C codebase कहना भी inaccurate है। HACL* C में compile होता है, लेकिन वह C library नहीं, बल्कि बिल्कुल अलग language में लिखा गया है
      ईमानदार title कुछ ऐसा होना चाहिए था: “F* के subset को partially safe Rust में compile करना, partially formalized”
    • क्या Rust खुद formally verified है? मेरी जानकारी में तो नहीं
    • formally verified C आखिर होता क्या है, और यह ज्यादा क्यों नहीं है, यह जानने की जिज्ञासा है
    • core difference क्या है, यह जानना चाहूंगा। क्या compliance को compiler flag से enforce किया जा सकता है?
  • 2002 में researchers ने C की safe dialect Cyclone पर paper publish किया था, और C code को manually Cyclone में port करते समय मौजूदा C code में safety bugs पाए थे
    ऐसे manual या automatic C transformations न सिर्फ safer languages के adoption को बढ़ा सकते हैं, बल्कि existing bugs उजागर करने की भी क्षमता रखते हैं
    [1] https://www.researchgate.net/profile/James-Cheney-2/publicat...

    • Cyclone अब supported नहीं है, core research project भी खत्म हो चुका है, और developers भी दूसरे कामों में चले गए हैं
      Cyclone के कई ideas Rust में आ गए, और code को मेहनत करके चलाया जा सकता है, लेकिन modern 64-bit platforms पर यह सीधे build नहीं होता
      http://cyclone.thelanguage.org
  • मैंने C2Rust को पहले step के तौर पर इस्तेमाल करके C projects समेत कुछ projects को Rust में port किया है, और कुछ conclusions निकाले हैं

    1. C program को Rust में ले जाने पर, भले ही उसमें unsafe शामिल हो, Rust की strong constraints—जैसे bounds checking और strict signatures—की वजह से bugs अक्सर जल्दी सामने आ जाते हैं
    2. मुझे नहीं लगता कि automatic C→Rust conversion पूरी तरह solve हो सकती है। C program का design Rust से fundamentally अलग होता है, और safe बनाने के लिए काफी redesign चाहिए
    3. कुछ मामलों में exact semantics preserve करते हुए C से Rust में ले जाना impossible है, क्योंकि unsafety design में ही inherent हो सकती है
      फिर भी tools porting के लिए essential हैं, और tools जितने बेहतर होंगे, process उतनी smooth होगी
    • “fast and safe Rust” में automatic conversion मुश्किल है, लेकिन सामान्य safe Rust में automatic conversion कहीं आसान है
      memory को array के रूप में represent करें और pointers को उस array के indices की तरह treat करें। तब unchecked pointer arithmetic या union जैसे C behaviors को borrow checker से लड़े बिना represent किया जा सकता है, और semantics भी preserve रहती हैं। C→Java में भी काफी पहले से इसी तरह की techniques इस्तेमाल होती रही हैं
      हालांकि ऐसे conversion की value unclear है। यह असल में C को wasm में compile करने जैसा है, लेकिन धीमा; और result code technically “safe” हो, तब भी buffer overflow गलत state बना सकता है या dangling pointer ऐसे context में data access संभव बना सकता है जहां इसकी अनुमति नहीं होनी चाहिए
    • “unsafety design में inherent हो सकती है” वाली बात से मैं principle में सहमत हूं, और अपने experience में भी मुझे यह strongly महसूस हुआ है, लेकिन discussion को concrete बनाने के लिए कोई simple example हो तो अच्छा होगा
  • मैं लेखक हूँ। अलग-अलग threads में आई कुछ बातों को समेट दूँ तो शायद मदद मिले

    1. यह arxiv पर डाला गया एक academic paper है, C→Rust समस्या हल कर देने का दावा करने वाली किसी नई product announcement नहीं। इसे PL conference में submit किया गया है, और FOSDEM जैसे open-source event talk की तुलना में audience और expectations अलग हैं
    2. approach सीधा है। C को safe Rust में translate करने की constraint से शुरू करके, हमने देखा कि सही तरह से काम करने वाला छोटा C subset, slice-splitting inference, error कर सकने वाला translation, और abort हो सकने वाले programs जैसी चीज़ें चाहिए। हमने इसे अपने पास मौजूद target—F* के अंदर embedded C—पर evaluate किया, और दिखाया कि Firefox, Python आदि mainstream software में इस्तेमाल होने वाली बड़ी C libraries में, इस constraint के तहत यह काफी scale करता है। हम यह दावा नहीं करते कि Firefox को automatically Rust में दोबारा लिखा जा सकता है
    3. research आम तौर पर ऐसे ही आगे बढ़ती है। हमें design space में एक interesting point दिखा; हम यह दावा नहीं करते कि यह सारी problems solve करता है, लेकिन C→Rust translation field में आगे की progress खोल सकने वाला idea मानते हैं। कोई existing tool इस approach को subset में fit होने वाले code पर इस्तेमाल कर सकता है, और जो हिस्से fit नहीं होते वहाँ unsafe Rust पर fallback कर सकता है
    4. यह final version नहीं है। हम actual C frontend को libclang से बना रहे हैं, और यह guarantee करने के तरीके भी explore कर रहे हैं कि generated Rust out-of-bounds access न बनाए। उदाहरण के लिए Z3 को verification conditions export करने जैसा सोचा जा रहा है। अगर reviewers को लगे कि और काम चाहिए, तो हम improve करके फिर submit कर सकते हैं; और अगर वे मानें कि यह field active है और दूसरे लोग ideas से benefit ले सकते हैं, तो paper accept हो जाए तो और अच्छा
  • सच में सवाल यह है कि यह करना क्यों है
    अगर यह ऐसी technology है जो industrial apps को C से Rust में सचमुच convert कर सकती है, तो लगता है कि existing C apps को ज्यादा आसानी से bulletproof भी बनाया जा सकता है। बस ऐसा analysis बनाना होगा जिसे static analyzers या test generators जैसे existing tools में डाला जा सके
    इसी तरह safe wrappers generate करके verified C के साथ नया code Rust में लिखने दिया जा सकता है। नए code को Rust के फायदे मिलेंगे, existing code safe confirm होगा, और interfaces भी ज्यादा safe होंगे
    पूरी translator शायद ideal हो सकती है, क्योंकि long term में codebase की language एक ही हो तो अच्छा है। लेकिन existing C/C++ के लिए low false-positive वाला one-click safety hardening अभी भी सबसे बड़ी जरूरत है। Google के compiler tools या ForAllSecure के Mayhem की तरह C के अंदर bad structures को automatically fix करना भी संभव हो सकता है

    • कुछ C programs को safe बनाया ही नहीं जा सकता, इसलिए “industrial apps को Rust में convert करने वाली technology हो तो C apps को ज्यादा आसानी से bulletproof किया जा सकता है” कहना सही नहीं है
      वजह यह हो सकती है कि वे undefined behavior या unspecified behavior पर depend करते हों, या appropriate safety checks लगाने पर acceptable input domain इतना छोटा हो जाए कि program बेकार हो जाए
      safe language में translate करने से input की expressiveness बनाए रखते हुए runtime पर correct behavior को statically guarantee किया जा सकता है, इसलिए ऐसे cases में यह objectively बेहतर है
      “field-proven C” जैसी चीज़ भी, जैसा कि अनगिनत critical vulnerabilities दिखाती हैं, मौजूद मानना मुश्किल है। असल में जो है वह C है जो काफी बार काफी अच्छे से काम करता है, इसलिए useful लगता है
      पुराने code को किस्मत से safe मान लिया जाता है, साबित नहीं किया गया होता। “proof” का, खासकर ऐसे paper के context में, एक खास मतलब है, और भारी बहुमत C code strict mathematical standard पर proven नहीं है। इसके उलट Rust type system mathematically correct proven है
      पूरा translator इस पर निर्भर है कि आप क्या छोड़ सकते हैं। performance, input domain, output range, code readability वगैरह छोड़ने को तैयार हों तो कुछ हद तक संभव होगा, लेकिन जैसे ही आप इन सभी पहलुओं में sound और complete translator चाहने लगते हैं, problem शुरू होती है
  • सीधे-सादे तरीके से Rust में translate करने पर safe हिस्से और unsafe हिस्से mix नहीं हो जाते? तब manual work में सिर्फ unsafe areas की safety check करनी होगी। यह शुरुआत से Rust लिखने जैसा ही है
    अगर result का 90% unsafe नहीं है, तो काफी फायदा लग सकता है

    • सच में यही बात है। किसी ने OpenJPEG को c2rust से low-level unsafe Rust में convert करके देखा था
      OpenJPEG एक specific test case में segfault करने के लिए known था, और जब वही test Rust version पर चलाया गया, तो corresponding Rust code में उसी जगह segfault हुआ। कम से कम compatibility तो बनी रही
      लेकिन वह approach dead end है। progress के लिए translator को C के common idioms पहचानकर उन्हें target language के natural form में उठाना होगा। Rust में “compile” करने पर unsafe C-style pointer manipulation function calls से भरा भयानक Rust बनता है
      सबसे बड़ी lifting problem mostly pointers से जुड़ी है। इस paper का सबसे promising result C pointer arithmetic को Rust slices में बदलने का तरीका ढूँढना है। slices C pointer arithmetic द्वारा किए जाने वाले ज्यादातर काम कर सकते हैं, और अब किसी ने उस translation को automate किया है। जो pointer arithmetic translate नहीं हो पाता, उसे बहुत suspicious मानना चाहिए
      C में array की ओर point करने वाले raw pointer के साथ implicitly एक length जुड़ी है, ऐसा सोचना useful है। वह length C source में दिखाई नहीं देती, लेकिन program state के function के रूप में कहीं मौजूद होती है। वह constant हो सकती है, malloc request size हो सकती है, या function parameter हो सकती है। maintenance programmer के लिए array length ढूँढना आम तौर पर बहुत मुश्किल नहीं होता
      यह LLM के लिए suitable problem हो सकती है। “इस code को देखकर array foo की length क्या है, यह ढूँढो” पूछकर, फिर non-LLM translator को Rust conversion guide करने देना। अगर LLM गलत हुआ, तो Rust index error देगा या बहुत बड़ा array होगा, लेकिन unsafe नहीं होगा। C में array size information के idioms काफी standardized हैं, इसलिए ज्यादातर cases में सही guess किया जा सकेगा। खासकर LLM comments भी पढ़ सकता है
    • naive translation लगभग पूरा unsafe Rust code बनाएगा। क्योंकि references की जगह raw pointers हर जगह इस्तेमाल होंगे
      C code Rust के aliasing model और borrow checker constraints को ध्यान में रखकर नहीं लिखा जाता, इसलिए उसे references में translate करना मुश्किल है
  • यह सिर्फ़ एक बहुत छोटे C subset को compile करने की बात है। असल में यह इतना छोटा हो सकता है कि व्यावहारिक रूप से बेकार हो
    ऐसे approach से मेरी उम्मीदें कम हैं। C code की static analysis से जो सीमाएँ संभव हैं, उनसे यह ज़रूर टकराएगा। ऊपर से Rust को target चुनने की वजह से समस्या बेवजह कठिन हो गई है। Rust का ownership model असली C programs के चलने के तरीके से बहुत अलग है

    • Rust का ownership model C translation के लिए काफ़ी करीब है। बस इसमें ज़्यादा explicit और strong types होते हैं, इसलिए translator को यह समझना होगा कि free-form C code क्या करना चाह रहा है और उसे Rust idioms पर map करना होगा
      उदाहरण के लिए C के buffer की स्वाभाविक रूप से length होती है, लेकिन C में length pointer से explicit रूप से बंधी नहीं होती। इसलिए translator को infer करना होगा कि C program length को कैसे track कर रहा है और उसे slice में बदलना होगा। length अगर explicit variable भी हो तो आसान नहीं है, और अगर वह calculated हो या “end के बाद वाला pointer” जैसे रूप में बदली हुई हो तो और मुश्किल हो जाता है
      bool should_free_this_pointer जैसे C patterns को भी Rust के Owned/Borrowed enum में ले जाया जा सकता है, लेकिन infer करना होगा कि कौन-सा allocation किस boolean से जुड़ा है और borrowed variant की असली safe range कहाँ तक है
    • Interface language के रूप में यह अच्छा हो सकता है। bindings के लिए उपयोगी है
    • आखिरकार लोग शायद इसमें LLM डाल देंगे और कहेंगे कि अगर वह भारी मात्रा में ऐसा code hallucinate करे जो देखने में ठीक-ठाक fit बैठता हो, तो भी ठीक है
      फिर भी मैं सहमत हूँ कि arbitrary C से idiomatic Rust बनाना कठिन होगा। यानी यह “लगभग ठीक” स्तर का होगा
  • सोच रहा हूँ कि यह Zig के C translation feature से कैसे compare होता है
    Zig नया code Zig में और legacy code C में रखने वाला mixed environment बनाने, translation या interoperability करने, और C compiler की भूमिका निभाने में काफ़ी अच्छा दिखता है
    Linux kernel maintainers Rust के बजाय Zig को C replacement के तौर पर नहीं देखते, इसकी कोई बहुत अच्छी वजह होगी। मैं अनुमान लगाने लायक इतना नहीं जानता, इसलिए बेहतर जानने वाले लोग समझाएँ तो अच्छा होगा

    • Rust “C का replacement” कम और C में जोड़ा गया tool ज़्यादा है। Torvalds आदि ने जिसकी value मानी और kernel में allow किया, और kernel code का ज़्यादातर हिस्सा C में ही लिखा जाता रहेगा
      मैं kernel maintainer नहीं हूँ, लेकिन अंदाज़ा लगाऊँ तो Rust को Zig पर चुने जाने की दो बड़ी वजहें यह हो सकती हैं कि language बेहतर compile-time guarantees देती है और adoption speed भी तेज़ है
      industry की बड़ी companies API के लिए Rust native code या maintained Rust bindings देने के लिए काफ़ी काम कर रही हैं। Windows developers भी अपने kernel के कुछ हिस्सों को Rust में फिर से लिख रहे हैं। यह काफ़ी समय से चल रही movement है, और उम्मीद है रुकेगी नहीं
      Maintainers को लग सकता है कि Zig, C की तुलना में पर्याप्त benefits नहीं देता। उनमें से कई अभी भी Rust के ख़िलाफ़ हैं
    • मेरी समझ में ज़्यादातर kernel maintainers C को किसी भी चीज़ से replace करना नहीं चाहते
      Zig की C के साथ interoperability Rust से कहीं बेहतर है, लेकिन यह memory safe नहीं है और stabilized भी नहीं है। C world में Zig adoption काफ़ी बढ़ेगा, लेकिन इसे Rust से सीधे competition में मानना मुश्किल है
      मेरे इलाके में कोई भी Rust adopt नहीं कर रहा, और C++ वाले C++ में ही बने हुए हैं। शुरुआत में Rust में कुछ interest था, लेकिन जिन companies को मैं जानता हूँ उनमें किसी में भी यह जम नहीं पाया। यह शायद वैसी ही वजह है जैसे Go युवा companies में बहुत बढ़ा, लेकिन traditional Java/C# companies में अच्छी तरह नहीं घुस पाया। technically भले ही बात समझ में आए, पर यह बहुत बड़ा change-management task है
      Zig उन programs में momentum पा रहा है जहाँ dynamic memory allocation की ज़रूरत नहीं होती, लेकिन उससे आगे बहुत ज़्यादा नहीं
    • Zig अभी kernel के लिए consider किए जाने जितना mature नहीं है
      इसमें अब भी नियमित रूप से breaking changes आते हैं, जो अभी Zig के लिए अच्छी बात है लेकिन Linux जैसे विशाल और लंबे समय तक चलने वाले codebase के लिए अच्छा नहीं है। Compiler bugs भी आते हैं
      यह मैं Zig की दिशा को कुल मिलाकर पसंद करने वाले व्यक्ति के तौर पर कह रहा हूँ
    • Zig अभी 1.0 नहीं है और backward compatibility guarantee बिल्कुल नहीं है। यह लगभग कहीं इस्तेमाल नहीं हुआ है, और इसके कुछ हिस्से promising दिखते हों तो भी इसने अभी अपनी value साबित नहीं की है
    • शायद इसलिए भी कि Zig memory safe नहीं है
  • सोच रहा हूँ कि C2Rust जैसे tools इसका इस्तेमाल करके formally correct code generate कर पाएँगे या नहीं
    यह भी जानना चाहूँगा कि authors ने कितना काम manually किया, या कोई चीज़ चला कर Rust code generate किया। अगर ऐसा है तो Rust generate करने वाला code कहाँ है, यह नहीं पता, और source repository link भी नहीं दिखता

    • Paper में लिखा है कि review process खत्म होने के बाद, यानी आम तौर पर paper के official publication के बाद, वे इस development artifact को open source license के तहत release करेंगे
  • अगर C library चलती है, यानी यह formally proved नहीं है कि उसमें कोई समस्या नहीं है लेकिन ज़्यादातर ठीक चलती है, तो सोचता हूँ कि translate करने के लिए unsafe Rust क्यों न इस्तेमाल करें
    Rust में कुल मिलाकर libraries की कमी है, इसलिए मुझे इसमें value दिखती है। आखिरकार यह किसी C में लिखे dll/so को इस्तेमाल करने से बहुत अलग नहीं है, जो कुछ situations में unsafe हो सकता है