{"record":{"id":"b36a81f897756465","repo":"in3rsha/sha256-animation","slug":"invalid-hex-string-input","errorCode":null,"errorMessage":"Invalid hex string: #{input}","messagePattern":"Invalid hex string: #(.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"sha256lib.rb","lineNumber":84,"sourceCode":"# Detect input type base on prefix (i.e. binary, hex, or otherwise just a string)\ndef input_type(input)\n  # Check if input is referencing a file\n  if(File.file?(input))\n  \treturn \"file\"\n  else\n\t  # Check for hex or binary prefix\n\t  case input[0..1]\n\t  when \"0b\"\n\t\t# check it's a valid binary string\n\t\tif input[2..-1] =~ /[^0-1]/ # only 1s and 0s\n\t\t  puts \"Invalid binary string: #{input}\"\n\t\t  exit\n\t\tend\n\t\treturn \"binary\"\n\t  when \"0x\"\n\t\t# check it's a valid hex string\n\t\tif input[2..-1] !~ /^[0-9A-F]+$/i # only hex chars (case-insensitive)\n\t\t  puts \"Invalid hex string: #{input}\"\n\t\t  exit\n\t\tend\n\t\treturn \"hex\"\n\t  else\n\t\treturn \"string\"\n\t  end\n  end\nend\n\n# Convert input (hex, ascii) to array of bytes\ndef bytes(input, type)\n  case type\n  when \"binary\"\n    bin = input[2..-1] # trim 0b prefix\n    if (bin.size % 8 == 0) # if we have been given a bitstring that makes up an exact number of bytes (8 bits in a byte)\n      bytes = bin.scan(/.{8}/).map {|byte| byte.to_i(2)} # convert the bits to array of bytes (in decimal)\n    else\n      bytes = \"(bitstring is not an exact amount of bytes)\" # helpful note","sourceCodeStart":66,"sourceCodeEnd":102,"githubUrl":"https://github.com/in3rsha/sha256-animation/blob/871e976d69e66474ef5239ee82031b7d87cbcafc/sha256lib.rb#L66-L102","documentation":"The counterpart of the binary check in input_type() (sha256lib.rb): an argument starting with 0x must have a remainder that fully matches ^[0-9A-F]+$ case-insensitively — at least one character, hex digits only. Anything else, including an empty payload after 0x, prints this message and exits before hashing starts. The guard exists because the next step, bytes(), feeds the payload straight into Ruby pack('H*'), which cannot convert non-hex characters.","triggerScenarios":"input_type('0xzz12') or ruby sha256.rb 0xg1 (non-hex letters); input_type('0x') (empty payload fails the one-or-more rule); '0x0xff' (prefix doubled by concatenation); '0x1a 2b' (space). Plain text meant as a string that begins with 0x, for example hashing '0xprotocol' as ASCII, is caught too. Beware a trailing newline: it slips past this regex (the $ anchor matches before a final newline) and instead raises ArgumentError later inside pack('H*').","commonSituations":"Gluing strings together and doubling the 0x prefix ('0x' + '0xff'); copy-pasting hex that gained a space or was trimmed down to empty; command substitution leaving a trailing newline; intending ASCII text that starts with 0x.","solutions":["Clean the payload after 0x until it contains only 0-9 and a-f/A-F: remove a duplicated 0x, spaces and punctuation","Give the payload at least one hex digit — a bare '0x' is always rejected","If the text is meant as plain ASCII, drop the 0x prefix so input_type returns 'string'","In your own validation, anchor to the true start and end of the string (not ^ and $) and chomp newlines, so a value like 0xabc plus a trailing newline cannot reach pack('H*') and raise ArgumentError there"],"exampleFix":"# before\nruby sha256.rb '0x0xff12'  # -> Invalid hex string: 0x0xff12\nruby sha256.rb '0x'         # -> Invalid hex string: 0x\n\n# after\nruby sha256.rb '0xff12'     # valid hex (case-insensitive)","handlingStrategy":"validation","validationCode":"# run before input_type() or the sha256.rb CLI\npayload = input.to_s.chomp[2..].to_s\nbad_hex = input.to_s.start_with?('0x') && (payload.empty? || payload.match(/[^0-9a-fA-F]/))\nabort 'payload after 0x must be non-empty hex digits' if bad_hex\ntype = input_type(input)","typeGuard":"def valid_hex_literal?(s)\n  text = s.to_s\n  payload = text.chomp[2..].to_s\n  !text.start_with?('0x') || (!payload.empty? && payload.match(/[^0-9a-fA-F]/).nil?)\nend","tryCatchPattern":"begin\n  type = input_type(candidate)\nrescue SystemExit\n  warn 'sha256lib rejected the hex input'\nend","preventionTips":["chomp values from command substitution before passing them — a trailing newline survives this check only to raise ArgumentError inside pack('H*')","Concatenate payloads, never prefixes: build '0x' + payload once so the prefix is never doubled","In your own checks anchor to true string boundaries, not ^ and $, to catch trailing newlines","Treat an empty '0x' as invalid input early — the library requires at least one hex digit"],"tags":["ruby","sha256","input-validation","hex","cli"],"backgroundTag":"invalid-hex-string","analyzedSha":"871e976d69e66474ef5239ee82031b7d87cbcafc","analyzedAt":"2026-08-23T12:17:23.862Z","schemaVersion":2},"datasetVersion":"2026-08-23T16:17:53.355Z"}